You're correct that this is unsafe, but this isn't what auto does. You'd be assigning a variable x of type A an object of type A. Then what that code theoretically changes, you're now assigning variable x of type B an object of type B. auto just handles all the boilerplate. It will be type safe, it's just logically incorrect.
For example
public int foo()
{
return 1;
}
auto x = foo();
//is the same as
int x = foo();
And then you change it to this: public float foo()
{
return 1.0f;
}
auto x = foo();
//is the same as
float x = foo();
In either case you can go on to do stuff like 'float y = x / 10;' Because they're both valid operators. But there can be logical inconsistencies, like the integer division problem that will occur if x is an int. Then again, you probably shouldn't use auto for something as simple as int or float. But 'auto foobar = new vector<int>;' is a very clear statement, and if you replace vector with something else, odds are the compiler will throw a fit with any later methods you attempt to call.I haven't written C++ in a while, so I hope I didn't butcher the examples too much. I simply typed them into the comment box.
The definition of type-safe could be extended to mean what you say, it's not really a term that is set in stone. But I've always used type safety to mean preventing type-based syntax errors, not semantic errors. If it's more common to do otherwise, I'd be happy to be corrected.