Skip to content

Commit 2b1444e

Browse files
committed
Fixed a few small bugs.
1 parent ed844c1 commit 2b1444e

File tree

7 files changed

+64
-0
lines changed

7 files changed

+64
-0
lines changed

src/semcheck/traverse.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,9 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>,
801801
compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target)
802802
{
803803
changes.add_change(TypeChanged { error: err }, orig_def_id, None);
804+
805+
// bail out after a type error
806+
return;
804807
}
805808

806809
compcx.check_bounds_bidirectional(changes,
@@ -944,6 +947,9 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>,
944947

945948
if let Some(err) = error {
946949
changes.add_change(TypeChanged { error: err }, orig_item_def_id, None);
950+
951+
// bail out after a type error
952+
return true;
947953
}
948954

949955
compcx.check_bounds_bidirectional(changes,

src/semcheck/typeck.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> {
205205
-> Option<Vec<Predicate<'tcx2>>>
206206
{
207207
use rustc::ty::Lift;
208+
debug!("check_bounds_error: orig env: {:?}, target did: {:?}, target substs: {:?}",
209+
orig_param_env,
210+
target_def_id,
211+
target_substs);
208212

209213
let mut bound_cx = BoundContext::new(self.infcx, orig_param_env);
210214
bound_cx.register(target_def_id, target_substs);

tests/cases/infer_regress/new.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn abc<A>(_: A) { }
2+
3+
pub struct Abc<A>(A, ());

tests/cases/infer_regress/old.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn abc<A>(a: A) -> A {
2+
a
3+
}
4+
5+
pub struct Abc<A>(A, A);

tests/cases/infer_regress/stdout

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version bump: 1.0.0 -> (breaking) -> 2.0.0
2+
warning: breaking changes in `abc`
3+
--> $REPO_PATH/tests/cases/infer_regress/new.rs:1:1
4+
|
5+
1 | pub fn abc<A>(_: A) { }
6+
| ^^^^^^^^^^^^^^^^^^^^^^^
7+
|
8+
= warning: type error: expected type parameter, found () (breaking)
9+
10+
warning: breaking changes in `Abc`
11+
--> $REPO_PATH/tests/cases/infer_regress/new.rs:3:1
12+
|
13+
3 | pub struct Abc<A>(A, ());
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= warning: type error: expected type parameter, found () (breaking)
17+

tests/dump

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<eddyb> we can't use the trait system for inherent impls
2+
you have to basically have a (DefId, AssociatedKind, hir::Name) => Vec</*impl*/ DefId> map
3+
and manually do what the trait system does for trait impls
4+
namely, generate fresh infer vars for the impl you want to match *against*, substitute that
5+
in its type_of (which is its Self) and then eq the type you want to check against that
6+
if it didn't error, the substs containing infer vars which you substituted in type_of are
7+
the params of the impl which you can then substitute in the associated items' signature
8+
sooo example
9+
old: impl Foo<u8> { fn foo() {} }
10+
new: impl<T> Foo<T> { fn foo() {} }
11+
(Foo, Method, "foo") => the one foo method in each
12+
or rather
13+
(old::Foo, Method, "foo") => old::...::foo
14+
(new::Foo, Method, "foo") => new::...::foo
15+
checking if old::...::foo is still valid means translating its "owner" (old::Foo), then
16+
pairing it with the fact that it's a Method and its name, to get (new::Foo, Method, "foo")
17+
which means for each in [new::...::foo] (well it's one element but you get the idea)
18+
you generate fresh substs. in this case T => $1
19+
substitute, so you get new::Foo<$1>
20+
match that against translate(old::Foo<u8>), i.e. new::Foo<u8>
21+
that will succeed and leave $1 equal to u8
22+
which means your substs are now T => u8
23+
oh I should've given it a signature. image it's -> u8 in old and -> T in new
24+
so the signature of the new method, substituted, is still -> u8
25+
and when you compare them that will succeed
26+
but if the new method were -> Option<T> then for T => u8 it'd be -> Option<u8> which is wrong
27+
and you'd notice the mismatch
28+
it's not that hard as long as you keep your code modular

tests/examples.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ test!(bounds, "tests/cases/bounds");
103103
test!(enums, "tests/cases/enums");
104104
test!(func, "tests/cases/func");
105105
test!(infer, "tests/cases/infer");
106+
test!(infer_regress, "tests/cases/infer_regress");
106107
test!(inherent_impls, "tests/cases/inherent_impls");
107108
test!(kind_change, "tests/cases/kind_change");
108109
test!(macros, "tests/cases/macros");

0 commit comments

Comments
 (0)