Skip to content

Commit 2181895

Browse files
matthewjasperAlexander Regueiro
authored and
Alexander Regueiro
committed
Handle impl trait in MIR type checked for assignments.
1 parent cf91584 commit 2181895

File tree

11 files changed

+368
-235
lines changed

11 files changed

+368
-235
lines changed

src/librustc/diagnostics.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,7 @@ specified exit code, use `std::process::exit`.
17391739

17401740
E0562: r##"
17411741
Abstract return types (written `impl Trait` for some trait `Trait`) are only
1742-
allowed as function and inherent impl return types or binding types.
1742+
allowed as function and inherent impl return types.
17431743
17441744
Erroneous code example:
17451745
@@ -1754,8 +1754,7 @@ fn main() {
17541754
}
17551755
```
17561756
1757-
Make sure `impl Trait` only appears in return-type position or as the type of a
1758-
binding.
1757+
Make sure `impl Trait` only appears in return-type position.
17591758
17601759
```
17611760
fn count_to_n(n: usize) -> impl Iterator<Item=usize> {

src/librustc/hir/lowering.rs

+49-8
Original file line numberDiff line numberDiff line change
@@ -1284,12 +1284,18 @@ impl<'a> LoweringContext<'a> {
12841284
))
12851285
}
12861286
ImplTraitContext::Disallowed => {
1287+
let allowed_in = if self.sess.features_untracked()
1288+
.impl_trait_in_bindings {
1289+
"bindings or function and inherent method return types"
1290+
} else {
1291+
"function and inherent method return types"
1292+
};
12871293
span_err!(
12881294
self.sess,
12891295
t.span,
12901296
E0562,
1291-
"`impl Trait` not allowed outside of function \
1292-
and inherent method return types or bindings"
1297+
"`impl Trait` not allowed outside of {}",
1298+
allowed_in,
12931299
);
12941300
hir::TyKind::Err
12951301
}
@@ -2206,8 +2212,10 @@ impl<'a> LoweringContext<'a> {
22062212
let impl_trait_ty = self.lower_existential_impl_trait(
22072213
span, Some(fn_def_id), return_impl_trait_id, |this| {
22082214
let output_ty = match output {
2209-
FunctionRetTy::Ty(ty) =>
2210-
this.lower_ty(ty, ImplTraitContext::Existential(Some(fn_def_id))),
2215+
FunctionRetTy::Ty(ty) => {
2216+
let impl_trait_owner_id = *this.current_impl_trait_owner.last().unwrap();
2217+
this.lower_ty(ty, ImplTraitContext::Existential(Some(impl_trait_owner_id)))
2218+
}
22112219
FunctionRetTy::Default(span) => {
22122220
let LoweredNodeId { node_id, hir_id } = this.next_id();
22132221
P(hir::Ty {
@@ -2702,14 +2710,31 @@ impl<'a> LoweringContext<'a> {
27022710
ItemKind::Static(ref t, m, ref e) => {
27032711
let value = self.lower_body(None, |this| this.lower_expr(e));
27042712
hir::ItemKind::Static(
2705-
self.lower_ty(t, ImplTraitContext::Disallowed),
2713+
self.lower_ty(
2714+
t,
2715+
if self.sess.features_untracked().impl_trait_in_bindings {
2716+
ImplTraitContext::Existential(None)
2717+
} else {
2718+
ImplTraitContext::Disallowed
2719+
}
2720+
),
27062721
self.lower_mutability(m),
27072722
value,
27082723
)
27092724
}
27102725
ItemKind::Const(ref t, ref e) => {
27112726
let value = self.lower_body(None, |this| this.lower_expr(e));
2712-
hir::ItemKind::Const(self.lower_ty(t, ImplTraitContext::Disallowed), value)
2727+
hir::ItemKind::Const(
2728+
self.lower_ty(
2729+
t,
2730+
if self.sess.features_untracked().impl_trait_in_bindings {
2731+
ImplTraitContext::Existential(None)
2732+
} else {
2733+
ImplTraitContext::Disallowed
2734+
}
2735+
),
2736+
value
2737+
)
27132738
}
27142739
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
27152740
let fn_def_id = self.resolver.definitions().local_def_id(id);
@@ -3258,6 +3283,22 @@ impl<'a> LoweringContext<'a> {
32583283
}
32593284
ids
32603285
},
3286+
ItemKind::Static(ref ty, ..) => {
3287+
let mut ids = smallvec![hir::ItemId { id: i.id }];
3288+
if self.sess.features_untracked().impl_trait_in_bindings {
3289+
let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
3290+
visitor.visit_ty(ty);
3291+
}
3292+
ids
3293+
},
3294+
ItemKind::Const(ref ty, ..) => {
3295+
let mut ids = smallvec![hir::ItemId { id: i.id }];
3296+
if self.sess.features_untracked().impl_trait_in_bindings {
3297+
let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
3298+
visitor.visit_ty(ty);
3299+
}
3300+
ids
3301+
},
32613302
_ => smallvec![hir::ItemId { id: i.id }],
32623303
}
32633304
}
@@ -3817,8 +3858,8 @@ impl<'a> LoweringContext<'a> {
38173858
}
38183859
ExprKind::Block(ref blk, opt_label) => {
38193860
hir::ExprKind::Block(self.lower_block(blk,
3820-
opt_label.is_some()),
3821-
self.lower_label(opt_label))
3861+
opt_label.is_some()),
3862+
self.lower_label(opt_label))
38223863
}
38233864
ExprKind::Assign(ref el, ref er) => {
38243865
hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)))

src/librustc/ty/relate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
361361
let tcx = relation.tcx();
362362
let a_sty = &a.sty;
363363
let b_sty = &b.sty;
364-
debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
364+
debug!("super_relate_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
365365
match (a_sty, b_sty) {
366366
(&ty::Infer(_), _) |
367367
(_, &ty::Infer(_)) =>

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

+15-132
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,8 @@
1717
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
1818
//! contain revealed `impl Trait` values).
1919
20-
use borrow_check::nll::renumber;
21-
use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
2220
use borrow_check::nll::universal_regions::UniversalRegions;
23-
use rustc::hir::def_id::DefId;
24-
use rustc::infer::InferOk;
2521
use rustc::mir::*;
26-
use rustc::traits::query::type_op::custom::CustomTypeOp;
27-
use rustc::traits::{ObligationCause, PredicateObligations};
28-
use rustc::ty::subst::Subst;
2922
use rustc::ty::Ty;
3023

3124
use rustc_data_structures::indexed_vec::Idx;
@@ -37,16 +30,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
3730
pub(super) fn equate_inputs_and_outputs(
3831
&mut self,
3932
mir: &Mir<'tcx>,
40-
mir_def_id: DefId,
4133
universal_regions: &UniversalRegions<'tcx>,
42-
universal_region_relations: &UniversalRegionRelations<'tcx>,
4334
normalized_inputs_and_output: &[Ty<'tcx>],
4435
) {
45-
let tcx = self.infcx.tcx;
46-
4736
let (&normalized_output_ty, normalized_input_tys) =
4837
normalized_inputs_and_output.split_last().unwrap();
49-
let infcx = self.infcx;
5038

5139
// Equate expected input tys with those in the MIR.
5240
let argument_locals = (1..).map(Local::new);
@@ -77,111 +65,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
7765

7866
// Return types are a bit more complex. They may contain existential `impl Trait`
7967
// types.
80-
let param_env = self.param_env;
8168
let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
8269
let output_span = mir.local_decls[RETURN_PLACE].source_info.span;
83-
let opaque_type_map =
84-
self.fully_perform_op(
85-
Locations::All(output_span),
86-
ConstraintCategory::BoringNoLocation,
87-
CustomTypeOp::new(
88-
|infcx| {
89-
let mut obligations = ObligationAccumulator::default();
90-
91-
let dummy_body_id = ObligationCause::dummy().body_id;
92-
let (output_ty, opaque_type_map) =
93-
obligations.add(infcx.instantiate_opaque_types(
94-
mir_def_id,
95-
dummy_body_id,
96-
param_env,
97-
&normalized_output_ty,
98-
));
99-
debug!(
100-
"equate_inputs_and_outputs: instantiated output_ty={:?}",
101-
output_ty
102-
);
103-
debug!(
104-
"equate_inputs_and_outputs: opaque_type_map={:#?}",
105-
opaque_type_map
106-
);
107-
108-
debug!(
109-
"equate_inputs_and_outputs: mir_output_ty={:?}",
110-
mir_output_ty
111-
);
112-
obligations.add(
113-
infcx
114-
.at(&ObligationCause::dummy(), param_env)
115-
.eq(output_ty, mir_output_ty)?,
116-
);
117-
118-
for (&opaque_def_id, opaque_decl) in &opaque_type_map {
119-
let opaque_defn_ty = tcx.type_of(opaque_def_id);
120-
let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs);
121-
let opaque_defn_ty = renumber::renumber_regions(
122-
infcx,
123-
&opaque_defn_ty,
124-
);
125-
debug!(
126-
"equate_inputs_and_outputs: concrete_ty={:?}",
127-
opaque_decl.concrete_ty
128-
);
129-
debug!("equate_inputs_and_outputs: opaque_defn_ty={:?}",
130-
opaque_defn_ty);
131-
obligations.add(
132-
infcx
133-
.at(&ObligationCause::dummy(), param_env)
134-
.eq(opaque_decl.concrete_ty, opaque_defn_ty)?,
135-
);
136-
}
137-
138-
debug!("equate_inputs_and_outputs: equated");
139-
140-
Ok(InferOk {
141-
value: Some(opaque_type_map),
142-
obligations: obligations.into_vec(),
143-
})
144-
},
145-
|| "input_output".to_string(),
146-
),
147-
).unwrap_or_else(|terr| {
148-
span_mirbug!(
149-
self,
150-
Location::START,
151-
"equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
152-
normalized_output_ty,
153-
mir_output_ty,
154-
terr
155-
);
156-
None
157-
});
158-
159-
// Finally, if we instantiated the opaque types successfully, we
160-
// have to solve any bounds (e.g., `-> impl Iterator` needs to
161-
// prove that `T: Iterator` where `T` is the type we
162-
// instantiated it with).
163-
if let Some(opaque_type_map) = opaque_type_map {
164-
for (opaque_def_id, opaque_decl) in opaque_type_map {
165-
self.fully_perform_op(
166-
Locations::All(infcx.tcx.def_span(opaque_def_id)),
167-
ConstraintCategory::OpaqueType,
168-
CustomTypeOp::new(
169-
|_cx| {
170-
infcx.constrain_opaque_type(
171-
opaque_def_id,
172-
&opaque_decl,
173-
universal_region_relations
174-
);
175-
Ok(InferOk {
176-
value: (),
177-
obligations: vec![],
178-
})
179-
},
180-
|| "opaque_type_map".to_string(),
181-
),
182-
).unwrap();
183-
}
184-
}
70+
if let Err(terr) = self.eq_opaque_type_and_type(
71+
mir_output_ty,
72+
normalized_output_ty,
73+
Locations::All(output_span),
74+
ConstraintCategory::BoringNoLocation,
75+
) {
76+
span_mirbug!(
77+
self,
78+
Location::START,
79+
"equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
80+
normalized_output_ty,
81+
mir_output_ty,
82+
terr
83+
);
84+
};
18585
}
18686

18787
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
@@ -204,20 +104,3 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
204104
}
205105
}
206106
}
207-
208-
#[derive(Debug, Default)]
209-
struct ObligationAccumulator<'tcx> {
210-
obligations: PredicateObligations<'tcx>,
211-
}
212-
213-
impl<'tcx> ObligationAccumulator<'tcx> {
214-
fn add<T>(&mut self, value: InferOk<'tcx, T>) -> T {
215-
let InferOk { value, obligations } = value;
216-
self.obligations.extend(obligations);
217-
value
218-
}
219-
220-
fn into_vec(self) -> PredicateObligations<'tcx> {
221-
self.obligations
222-
}
223-
}

0 commit comments

Comments
 (0)