Skip to content

Commit 2c2e2c5

Browse files
committed
Auto merge of #54942 - matthewjasper:wf-type-annotations, r=nikomatsakis
[NLL] Check user types are well-formed Also contains a change of span for AscribeUserType. I'm not quite sure if this was what @nikomatsakis was thinking. Closes #54620 r? @nikomatsakis
2 parents 945372d + c312e04 commit 2c2e2c5

File tree

42 files changed

+343
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+343
-134
lines changed

src/librustc/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
710710
/// e.g. via `let x: T`, then we carry that type here. The MIR
711711
/// borrow checker needs this information since it can affect
712712
/// region inference.
713-
pub user_ty: Option<CanonicalTy<'tcx>>,
713+
pub user_ty: Option<(CanonicalTy<'tcx>, Span)>,
714714

715715
/// Name of the local, used in debuginfo and pretty-printing.
716716
///

src/librustc/mir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ macro_rules! make_mir_visitor {
735735
local,
736736
source_info: *source_info,
737737
});
738-
if let Some(user_ty) = user_ty {
738+
if let Some((user_ty, _)) = user_ty {
739739
self.visit_user_ty(user_ty);
740740
}
741741
self.visit_source_info(source_info);

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -310,12 +310,12 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
310310
self.super_local_decl(local, local_decl);
311311
self.sanitize_type(local_decl, local_decl.ty);
312312

313-
if let Some(user_ty) = local_decl.user_ty {
313+
if let Some((user_ty, span)) = local_decl.user_ty {
314314
if let Err(terr) = self.cx.relate_type_and_user_type(
315315
local_decl.ty,
316316
ty::Variance::Invariant,
317317
user_ty,
318-
Locations::All(local_decl.source_info.span),
318+
Locations::All(span),
319319
ConstraintCategory::TypeAnnotation,
320320
) {
321321
span_mirbug!(
@@ -970,15 +970,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
970970
locations: Locations,
971971
category: ConstraintCategory,
972972
) -> Fallible<()> {
973-
relate_tys::relate_type_and_user_type(
973+
let ty = relate_tys::relate_type_and_user_type(
974974
self.infcx,
975975
a,
976976
v,
977977
b,
978978
locations,
979979
category,
980980
self.borrowck_context.as_mut().map(|x| &mut **x),
981-
)
981+
)?;
982+
self.prove_predicate(
983+
ty::Predicate::WellFormed(ty),
984+
locations,
985+
category,
986+
);
987+
Ok(())
982988
}
983989

984990
fn eq_opaque_type_and_type(

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use borrow_check::nll::constraints::OutlivesConstraint;
1212
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
13-
use rustc::infer::canonical::{Canonical, CanonicalVarInfos};
13+
use rustc::infer::canonical::{Canonical, CanonicalVarInfos, CanonicalVarValues};
1414
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1515
use rustc::mir::ConstraintCategory;
1616
use rustc::traits::query::Fallible;
@@ -70,7 +70,7 @@ pub(super) fn relate_type_and_user_type<'tcx>(
7070
locations: Locations,
7171
category: ConstraintCategory,
7272
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
73-
) -> Fallible<()> {
73+
) -> Fallible<Ty<'tcx>> {
7474
debug!(
7575
"sub_type_and_user_type(a={:?}, b={:?}, locations={:?})",
7676
a, b, locations
@@ -85,13 +85,24 @@ pub(super) fn relate_type_and_user_type<'tcx>(
8585
// variance to get the right relationship.
8686
let v1 = ty::Contravariant.xform(v);
8787

88-
TypeRelating::new(
88+
let mut type_relating = TypeRelating::new(
8989
infcx.tcx,
9090
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
9191
v1,
9292
b_variables,
93-
).relate(&b_value, &a)?;
94-
Ok(())
93+
);
94+
type_relating.relate(&b_value, &a)?;
95+
96+
Ok(b.substitute(
97+
infcx.tcx,
98+
&CanonicalVarValues {
99+
var_values: type_relating
100+
.canonical_var_values
101+
.into_iter()
102+
.map(|x| x.expect("unsubstituted canonical variable"))
103+
.collect(),
104+
},
105+
))
95106
}
96107

97108
struct TypeRelating<'me, 'gcx: 'tcx, 'tcx: 'me, D>

src/librustc_mir/build/matches/mod.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -292,30 +292,32 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
292292
..
293293
},
294294
user_ty: ascription_user_ty,
295+
user_ty_span,
295296
} => {
296297
let place =
297298
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
298299
unpack!(block = self.into(&place, block, initializer));
299300

300-
let source_info = self.source_info(irrefutable_pat.span);
301+
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
302+
let pattern_source_info = self.source_info(irrefutable_pat.span);
301303
self.cfg.push(
302304
block,
303305
Statement {
304-
source_info,
305-
kind: StatementKind::AscribeUserType(
306-
place.clone(),
307-
ty::Variance::Invariant,
308-
ascription_user_ty,
309-
),
306+
source_info: pattern_source_info,
307+
kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
310308
},
311309
);
312310

313-
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
311+
let ty_source_info = self.source_info(user_ty_span);
314312
self.cfg.push(
315313
block,
316314
Statement {
317-
source_info,
318-
kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
315+
source_info: ty_source_info,
316+
kind: StatementKind::AscribeUserType(
317+
place.clone(),
318+
ty::Variance::Invariant,
319+
ascription_user_ty,
320+
),
319321
},
320322
);
321323

@@ -489,7 +491,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
489491
pub fn visit_bindings(
490492
&mut self,
491493
pattern: &Pattern<'tcx>,
492-
mut pattern_user_ty: Option<CanonicalTy<'tcx>>,
494+
mut pattern_user_ty: Option<(CanonicalTy<'tcx>, Span)>,
493495
f: &mut impl FnMut(
494496
&mut Self,
495497
Mutability,
@@ -498,7 +500,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
498500
NodeId,
499501
Span,
500502
Ty<'tcx>,
501-
Option<CanonicalTy<'tcx>>,
503+
Option<(CanonicalTy<'tcx>, Span)>,
502504
),
503505
) {
504506
match *pattern.kind {
@@ -549,16 +551,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
549551
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
550552
self.visit_bindings(subpattern, None, f);
551553
}
552-
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
554+
PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => {
553555
// This corresponds to something like
554556
//
555557
// ```
556-
// let (p1: T1): T2 = ...;
558+
// let A::<'a>(_): A<'static> = ...;
557559
// ```
558560
//
559-
// Not presently possible, though maybe someday.
560-
assert!(pattern_user_ty.is_none());
561-
self.visit_bindings(subpattern, Some(user_ty), f)
561+
// FIXME(#47184): handle `pattern_user_ty` somehow
562+
self.visit_bindings(subpattern, Some((user_ty, user_ty_span)), f)
562563
}
563564
PatternKind::Leaf { ref subpatterns }
564565
| PatternKind::Variant {
@@ -1469,7 +1470,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14691470
num_patterns: usize,
14701471
var_id: NodeId,
14711472
var_ty: Ty<'tcx>,
1472-
user_var_ty: Option<CanonicalTy<'tcx>>,
1473+
user_var_ty: Option<(CanonicalTy<'tcx>, Span)>,
14731474
has_guard: ArmHasGuard,
14741475
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
14751476
pat_span: Span,

src/librustc_mir/build/matches/simplify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
6363
candidate: &mut Candidate<'pat, 'tcx>)
6464
-> Result<(), MatchPair<'pat, 'tcx>> {
6565
match *match_pair.pattern.kind {
66-
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
66+
PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => {
6767
candidate.ascriptions.push(Ascription {
68-
span: match_pair.pattern.span,
68+
span: user_ty_span,
6969
user_ty,
7070
source: match_pair.place.clone(),
7171
});

src/librustc_mir/hair/cx/block.rs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
9292
span: pattern.span,
9393
kind: Box::new(PatternKind::AscribeUserType {
9494
user_ty: *user_ty,
95+
user_ty_span: ty.span,
9596
subpattern: pattern
9697
})
9798
};

src/librustc_mir/hair/pattern/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub enum PatternKind<'tcx> {
7171
AscribeUserType {
7272
user_ty: CanonicalTy<'tcx>,
7373
subpattern: Pattern<'tcx>,
74+
user_ty_span: Span,
7475
},
7576

7677
/// x, ref x, x @ P, etc
@@ -692,6 +693,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
692693
kind = PatternKind::AscribeUserType {
693694
subpattern,
694695
user_ty,
696+
user_ty_span: span,
695697
};
696698
}
697699

@@ -1015,9 +1017,11 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
10151017
PatternKind::AscribeUserType {
10161018
ref subpattern,
10171019
user_ty,
1020+
user_ty_span,
10181021
} => PatternKind::AscribeUserType {
10191022
subpattern: subpattern.fold_with(folder),
10201023
user_ty: user_ty.fold_with(folder),
1024+
user_ty_span,
10211025
},
10221026
PatternKind::Binding {
10231027
mutability,

src/test/mir-opt/basic_assignment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ fn main() {
5555
// StorageDead(_3);
5656
// StorageLive(_4);
5757
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
58-
// AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
5958
// FakeRead(ForLet, _4);
59+
// AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
6060
// StorageLive(_5);
6161
// StorageLive(_6);
6262
// _6 = move _4;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/associated-types-subtyping-1.rs:36:13
3+
|
4+
LL | fn method2<'a,'b,T>(x: &'a T, y: &'b T)
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
...
9+
LL | let _c: <T as Trait<'b>>::Type = a; //~ ERROR E0623
10+
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
11+
12+
error: unsatisfied lifetime constraints
13+
--> $DIR/associated-types-subtyping-1.rs:44:12
14+
|
15+
LL | fn method3<'a,'b,T>(x: &'a T, y: &'b T)
16+
| -- -- lifetime `'b` defined here
17+
| |
18+
| lifetime `'a` defined here
19+
...
20+
LL | let b: <T as Trait<'b>>::Type = make_any();
21+
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
22+
23+
error: aborting due to 2 previous errors
24+

src/test/ui/associated-types/associated-types-subtyping-1.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
#![allow(unused_variables)]
1412

13+
fn make_any<T>() -> T { loop {} }
14+
1515
trait Trait<'a> {
1616
type Type;
1717

@@ -22,35 +22,35 @@ fn method1<'a,'b,T>(x: &'a T, y: &'b T)
2222
where T : for<'z> Trait<'z>, 'a : 'b
2323
{
2424
// Note that &'static T <: &'a T.
25-
let a: <T as Trait<'a>>::Type = loop { };
26-
let b: <T as Trait<'b>>::Type = loop { };
25+
let a: <T as Trait<'a>>::Type = make_any();
26+
let b: <T as Trait<'b>>::Type = make_any();
2727
let _c: <T as Trait<'a>>::Type = a;
2828
}
2929

3030
fn method2<'a,'b,T>(x: &'a T, y: &'b T)
3131
where T : for<'z> Trait<'z>, 'a : 'b
3232
{
3333
// Note that &'static T <: &'a T.
34-
let a: <T as Trait<'a>>::Type = loop { };
35-
let b: <T as Trait<'b>>::Type = loop { };
34+
let a: <T as Trait<'a>>::Type = make_any();
35+
let b: <T as Trait<'b>>::Type = make_any();
3636
let _c: <T as Trait<'b>>::Type = a; //~ ERROR E0623
3737
}
3838

3939
fn method3<'a,'b,T>(x: &'a T, y: &'b T)
4040
where T : for<'z> Trait<'z>, 'a : 'b
4141
{
4242
// Note that &'static T <: &'a T.
43-
let a: <T as Trait<'a>>::Type = loop { };
44-
let b: <T as Trait<'b>>::Type = loop { };
43+
let a: <T as Trait<'a>>::Type = make_any();
44+
let b: <T as Trait<'b>>::Type = make_any();
4545
let _c: <T as Trait<'a>>::Type = b; //~ ERROR E0623
4646
}
4747

4848
fn method4<'a,'b,T>(x: &'a T, y: &'b T)
4949
where T : for<'z> Trait<'z>, 'a : 'b
5050
{
5151
// Note that &'static T <: &'a T.
52-
let a: <T as Trait<'a>>::Type = loop { };
53-
let b: <T as Trait<'b>>::Type = loop { };
52+
let a: <T as Trait<'a>>::Type = make_any();
53+
let b: <T as Trait<'b>>::Type = make_any();
5454
let _c: <T as Trait<'b>>::Type = b;
5555
}
5656

src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
55
| ^^^^^^^^^
66

77
error: higher-ranked subtype error
8-
--> $DIR/hr-fn-aaa-as-aba.rs:32:9
8+
--> $DIR/hr-fn-aaa-as-aba.rs:32:12
99
|
1010
LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
11-
| ^
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

src/test/ui/nll/user-annotations/patterns.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ LL | y //~ ERROR
131131
| ^ returning this value requires that `'a` must outlive `'static`
132132

133133
error: unsatisfied lifetime constraints
134-
--> $DIR/patterns.rs:117:9
134+
--> $DIR/patterns.rs:117:18
135135
|
136136
LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
137137
| -- lifetime `'a` defined here
138138
LL | let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
139-
| ^^^^^^^ type annotation requires that `'a` must outlive `'static`
139+
| ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
140140

141141
error: aborting due to 14 previous errors
142142

src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0621]: explicit lifetime required in the type of `v`
2-
--> $DIR/region-object-lifetime-in-coercion.rs:18:9
2+
--> $DIR/region-object-lifetime-in-coercion.rs:18:12
33
|
44
LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
55
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
66
LL | let x: Box<Foo + 'static> = Box::new(v);
7-
| ^ lifetime `'static` required
7+
| ^^^^^^^^^^^^^^^^^^ lifetime `'static` required
88

99
error[E0621]: explicit lifetime required in the type of `v`
1010
--> $DIR/region-object-lifetime-in-coercion.rs:24:5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error: unsatisfied lifetime constraints
2-
--> $DIR/regions-addr-of-self.rs:17:13
2+
--> $DIR/regions-addr-of-self.rs:17:16
33
|
44
LL | pub fn chase_cat(&mut self) {
55
| - let's call the lifetime of this reference `'1`
66
LL | let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
7-
| ^ type annotation requires that `'1` must outlive `'static`
7+
| ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
88

99
error: aborting due to previous error
1010

0 commit comments

Comments
 (0)