summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-02-15 02:24:04 +0000
committerbors <bors@rust-lang.org>2020-02-15 02:24:04 +0000
commit19288ddfd6b3448c2c221d75610bff722a6582e8 (patch)
tree328dee8a45bac8f49f6a127c1ebd6e3966e1a749
parentAuto merge of #69172 - JohnTitor:rollup-6cbmwcw, r=JohnTitor (diff)
parentFix tests after rebase (diff)
downloadrust-19288ddfd6b3448c2c221d75610bff722a6582e8.tar.gz
rust-19288ddfd6b3448c2c221d75610bff722a6582e8.tar.bz2
rust-19288ddfd6b3448c2c221d75610bff722a6582e8.tar.xz
Auto merge of #67681 - matthewjasper:infer-regions-in-borrowck, r=nikomatsakis
Infer regions for opaque types in borrowck This is a step towards the goal of typeck not doing region inference. The commits up to `Arena allocate the result of mir_borrowck` are various bug fixes and prerequisites. The remaining commits move opaque type inference to borrow checking. r? @nikomatsakis
-rw-r--r--src/librustc/arena.rs3
-rw-r--r--src/librustc/infer/error_reporting/mod.rs6
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs11
-rw-r--r--src/librustc/infer/opaque_types/mod.rs132
-rw-r--r--src/librustc/mir/query.rs8
-rw-r--r--src/librustc/query/mod.rs22
-rw-r--r--src/librustc/ty/flags.rs2
-rw-r--r--src/librustc/ty/fold.rs7
-rw-r--r--src/librustc/ty/mod.rs15
-rw-r--r--src/librustc/ty/sty.rs4
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_ast_lowering/item.rs14
-rw-r--r--src/librustc_ast_lowering/lib.rs54
-rw-r--r--src/librustc_hir/hir.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs23
-rw-r--r--src/librustc_mir/borrow_check/mod.rs51
-rw-r--r--src/librustc_mir/borrow_check/nll.rs52
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs60
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs149
-rw-r--r--src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs68
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs142
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs45
-rw-r--r--src/librustc_mir_build/build/mod.rs47
-rw-r--r--src/librustc_typeck/check/writeback.rs5
-rw-r--r--src/librustc_typeck/collect.rs609
-rw-r--r--src/librustc_typeck/collect/type_of.rs661
-rw-r--r--src/librustc_typeck/impl_wf_check.rs21
-rw-r--r--src/libstd/future.rs3
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.nll.stderr11
-rw-r--r--src/test/ui/async-await/no-const-async.rs1
-rw-r--r--src/test/ui/async-await/no-const-async.stderr12
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs14
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr16
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs26
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr61
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.rs3
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr34
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs9
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.stderr10
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr150
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.rs49
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.stderr8
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs29
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr15
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs13
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr17
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr2
-rw-r--r--src/test/ui/impl-trait/nested-return-type.rs16
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs5
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr2
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs65
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr42
-rw-r--r--src/test/ui/impl-trait/unsafety-checking-cycle.rs32
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.rs52
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.stderr68
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr19
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.nll.stderr51
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.nll.stderr51
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.nll.stderr43
-rw-r--r--src/test/ui/self/elision/ref-struct-async.nll.stderr43
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-const.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs26
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs2
72 files changed, 1996 insertions, 1304 deletions
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index dd24268..33cbf6e 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -35,7 +35,8 @@ macro_rules! arena_types {
35 rustc::mir::Promoted, 35 rustc::mir::Promoted,
36 rustc::mir::BodyAndCache<$tcx> 36 rustc::mir::BodyAndCache<$tcx>
37 >, 37 >,
38 [] tables: rustc::ty::TypeckTables<$tcx>, 38 [decode] tables: rustc::ty::TypeckTables<$tcx>,
39 [decode] borrowck_result: rustc::mir::BorrowCheckResult<$tcx>,
39 [] const_allocs: rustc::mir::interpret::Allocation, 40 [] const_allocs: rustc::mir::interpret::Allocation,
40 [] vtable_method: Option<( 41 [] vtable_method: Option<(
41 rustc_hir::def_id::DefId, 42 rustc_hir::def_id::DefId,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 01390f2..327e1da 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -405,17 +405,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
405 } 405 }
406 406
407 RegionResolutionError::MemberConstraintFailure { 407 RegionResolutionError::MemberConstraintFailure {
408 opaque_type_def_id,
409 hidden_ty, 408 hidden_ty,
410 member_region, 409 member_region,
411 span: _, 410 span,
412 choice_regions: _,
413 } => { 411 } => {
414 let hidden_ty = self.resolve_vars_if_possible(&hidden_ty); 412 let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
415 opaque_types::unexpected_hidden_region_diagnostic( 413 opaque_types::unexpected_hidden_region_diagnostic(
416 self.tcx, 414 self.tcx,
417 Some(region_scope_tree), 415 Some(region_scope_tree),
418 opaque_type_def_id, 416 span,
419 hidden_ty, 417 hidden_ty,
420 member_region, 418 member_region,
421 ) 419 )
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index e0a8c3b..1b204e5 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet;
18use rustc_data_structures::graph::implementation::{ 18use rustc_data_structures::graph::implementation::{
19 Direction, Graph, NodeIndex, INCOMING, OUTGOING, 19 Direction, Graph, NodeIndex, INCOMING, OUTGOING,
20}; 20};
21use rustc_hir::def_id::DefId;
22use rustc_index::vec::{Idx, IndexVec}; 21use rustc_index::vec::{Idx, IndexVec};
23use rustc_span::Span; 22use rustc_span::Span;
24use std::fmt; 23use std::fmt;
@@ -95,13 +94,7 @@ pub enum RegionResolutionError<'tcx> {
95 /// Indicates a failure of a `MemberConstraint`. These arise during 94 /// Indicates a failure of a `MemberConstraint`. These arise during
96 /// impl trait processing explicitly -- basically, the impl trait's hidden type 95 /// impl trait processing explicitly -- basically, the impl trait's hidden type
97 /// included some region that it was not supposed to. 96 /// included some region that it was not supposed to.
98 MemberConstraintFailure { 97 MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> },
99 span: Span,
100 opaque_type_def_id: DefId,
101 hidden_ty: Ty<'tcx>,
102 member_region: Region<'tcx>,
103 choice_regions: Vec<Region<'tcx>>,
104 },
105} 98}
106 99
107struct RegionAndOrigin<'tcx> { 100struct RegionAndOrigin<'tcx> {
@@ -656,10 +649,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
656 let span = self.tcx().def_span(member_constraint.opaque_type_def_id); 649 let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
657 errors.push(RegionResolutionError::MemberConstraintFailure { 650 errors.push(RegionResolutionError::MemberConstraintFailure {
658 span, 651 span,
659 opaque_type_def_id: member_constraint.opaque_type_def_id,
660 hidden_ty: member_constraint.hidden_ty, 652 hidden_ty: member_constraint.hidden_ty,
661 member_region, 653 member_region,
662 choice_regions: choice_regions.collect(),
663 }); 654 });
664 } 655 }
665 } 656 }
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 7fef9d2..5ecd03e 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
93 pub origin: hir::OpaqueTyOrigin, 93 pub origin: hir::OpaqueTyOrigin,
94} 94}
95 95
96/// Whether member constraints should be generated for all opaque types
97pub enum GenerateMemberConstraints {
98 /// The default, used by typeck
99 WhenRequired,
100 /// The borrow checker needs member constraints in any case where we don't
101 /// have a `'static` bound. This is because the borrow checker has more
102 /// flexibility in the values of regions. For example, given `f<'a, 'b>`
103 /// the borrow checker can have an inference variable outlive `'a` and `'b`,
104 /// but not be equal to `'static`.
105 IfNoStaticBound,
106}
107
96impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 108impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
97 /// Replaces all opaque types in `value` with fresh inference variables 109 /// Replaces all opaque types in `value` with fresh inference variables
98 /// and creates appropriate obligations. For example, given the input: 110 /// and creates appropriate obligations. For example, given the input:
@@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315 debug!("constrain_opaque_types()"); 327 debug!("constrain_opaque_types()");
316 328
317 for (&def_id, opaque_defn) in opaque_types { 329 for (&def_id, opaque_defn) in opaque_types {
318 self.constrain_opaque_type(def_id, opaque_defn, free_region_relations); 330 self.constrain_opaque_type(
331 def_id,
332 opaque_defn,
333 GenerateMemberConstraints::WhenRequired,
334 free_region_relations,
335 );
319 } 336 }
320 } 337 }
321 338
@@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
324 &self, 341 &self,
325 def_id: DefId, 342 def_id: DefId,
326 opaque_defn: &OpaqueTypeDecl<'tcx>, 343 opaque_defn: &OpaqueTypeDecl<'tcx>,
344 mode: GenerateMemberConstraints,
327 free_region_relations: &FRR, 345 free_region_relations: &FRR,
328 ) { 346 ) {
329 debug!("constrain_opaque_type()"); 347 debug!("constrain_opaque_type()");
@@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
358 op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), 376 op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
359 }); 377 });
360 } 378 }
379 if let GenerateMemberConstraints::IfNoStaticBound = mode {
380 self.generate_member_constraint(
381 concrete_ty,
382 opaque_type_generics,
383 opaque_defn,
384 def_id,
385 );
386 }
361 return; 387 return;
362 } 388 }
363 389
@@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
398 // we will create a "in bound" like `'r in 424 // we will create a "in bound" like `'r in
399 // ['a, 'b, 'c]`, where `'a..'c` are the 425 // ['a, 'b, 'c]`, where `'a..'c` are the
400 // regions that appear in the impl trait. 426 // regions that appear in the impl trait.
427
428 // For now, enforce a feature gate outside of async functions.
429 self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
430
401 return self.generate_member_constraint( 431 return self.generate_member_constraint(
402 concrete_ty, 432 concrete_ty,
403 opaque_type_generics, 433 opaque_type_generics,
404 opaque_defn, 434 opaque_defn,
405 def_id, 435 def_id,
406 lr,
407 subst_arg,
408 ); 436 );
409 } 437 }
410 } 438 }
@@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
414 let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); 442 let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
415 debug!("constrain_opaque_types: least_region={:?}", least_region); 443 debug!("constrain_opaque_types: least_region={:?}", least_region);
416 444
445 if let GenerateMemberConstraints::IfNoStaticBound = mode {
446 if least_region != tcx.lifetimes.re_static {
447 self.generate_member_constraint(
448 concrete_ty,
449 opaque_type_generics,
450 opaque_defn,
451 def_id,
452 );
453 }
454 }
417 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { 455 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
418 tcx: self.tcx, 456 tcx: self.tcx,
419 op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), 457 op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
@@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
434 opaque_type_generics: &ty::Generics, 472 opaque_type_generics: &ty::Generics,
435 opaque_defn: &OpaqueTypeDecl<'tcx>, 473 opaque_defn: &OpaqueTypeDecl<'tcx>,
436 opaque_type_def_id: DefId, 474 opaque_type_def_id: DefId,
437 conflict1: ty::Region<'tcx>,
438 conflict2: ty::Region<'tcx>,
439 ) { 475 ) {
440 // For now, enforce a feature gate outside of async functions.
441 if self.member_constraint_feature_gate(
442 opaque_defn,
443 opaque_type_def_id,
444 conflict1,
445 conflict2,
446 ) {
447 return;
448 }
449
450 // Create the set of choice regions: each region in the hidden 476 // Create the set of choice regions: each region in the hidden
451 // type can be equal to any of the region parameters of the 477 // type can be equal to any of the region parameters of the
452 // opaque type definition. 478 // opaque type definition.
@@ -500,8 +526,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
500 hir::OpaqueTyOrigin::AsyncFn => return false, 526 hir::OpaqueTyOrigin::AsyncFn => return false,
501 527
502 // Otherwise, generate the label we'll use in the error message. 528 // Otherwise, generate the label we'll use in the error message.
503 hir::OpaqueTyOrigin::TypeAlias => "impl Trait", 529 hir::OpaqueTyOrigin::TypeAlias
504 hir::OpaqueTyOrigin::FnReturn => "impl Trait", 530 | hir::OpaqueTyOrigin::FnReturn
531 | hir::OpaqueTyOrigin::Misc => "impl Trait",
505 }; 532 };
506 let msg = format!("ambiguous lifetime bound in `{}`", context_name); 533 let msg = format!("ambiguous lifetime bound in `{}`", context_name);
507 let mut err = self.tcx.sess.struct_span_err(span, &msg); 534 let mut err = self.tcx.sess.struct_span_err(span, &msg);
@@ -549,13 +576,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
549 /// # Parameters 576 /// # Parameters
550 /// 577 ///
551 /// - `def_id`, the `impl Trait` type 578 /// - `def_id`, the `impl Trait` type
552 /// - `opaque_defn`, the opaque definition created in `instantiate_opaque_types` 579 /// - `substs`, the substs used to instantiate this opaque type
553 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of 580 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
554 /// `opaque_defn.concrete_ty` 581 /// `opaque_defn.concrete_ty`
555 pub fn infer_opaque_definition_from_instantiation( 582 pub fn infer_opaque_definition_from_instantiation(
556 &self, 583 &self,
557 def_id: DefId, 584 def_id: DefId,
558 opaque_defn: &OpaqueTypeDecl<'tcx>, 585 substs: SubstsRef<'tcx>,
559 instantiated_ty: Ty<'tcx>, 586 instantiated_ty: Ty<'tcx>,
560 span: Span, 587 span: Span,
561 ) -> Ty<'tcx> { 588 ) -> Ty<'tcx> {
@@ -571,12 +598,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
571 // `impl Trait` return type, resulting in the parameters 598 // `impl Trait` return type, resulting in the parameters
572 // shifting. 599 // shifting.
573 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); 600 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
574 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = opaque_defn 601 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
575 .substs 602 substs.iter().enumerate().map(|(index, subst)| (*subst, id_substs[index])).collect();
576 .iter()
577 .enumerate()
578 .map(|(index, subst)| (*subst, id_substs[index]))
579 .collect();
580 603
581 // Convert the type from the function into a type valid outside 604 // Convert the type from the function into a type valid outside
582 // the function, by replacing invalid regions with 'static, 605 // the function, by replacing invalid regions with 'static,
@@ -598,11 +621,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
598pub fn unexpected_hidden_region_diagnostic( 621pub fn unexpected_hidden_region_diagnostic(
599 tcx: TyCtxt<'tcx>, 622 tcx: TyCtxt<'tcx>,
600 region_scope_tree: Option<&region::ScopeTree>, 623 region_scope_tree: Option<&region::ScopeTree>,
601 opaque_type_def_id: DefId, 624 span: Span,
602 hidden_ty: Ty<'tcx>, 625 hidden_ty: Ty<'tcx>,
603 hidden_region: ty::Region<'tcx>, 626 hidden_region: ty::Region<'tcx>,
604) -> DiagnosticBuilder<'tcx> { 627) -> DiagnosticBuilder<'tcx> {
605 let span = tcx.def_span(opaque_type_def_id);
606 let mut err = struct_span_err!( 628 let mut err = struct_span_err!(
607 tcx.sess, 629 tcx.sess,
608 span, 630 span,
@@ -817,32 +839,48 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
817 839
818 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { 840 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
819 match r { 841 match r {
820 // ignore bound regions that appear in the type (e.g., this 842 // Ignore bound regions and `'static` regions that appear in the
821 // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. 843 // type, we only need to remap regions that reference lifetimes
822 ty::ReLateBound(..) | 844 // from the function declaraion.
823 845 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
824 // ignore `'static`, as that can appear anywhere 846 ty::ReLateBound(..) | ty::ReStatic => return r,
825 ty::ReStatic => return r, 847
826 848 // If regions have been erased (by writeback), don't try to unerase
827 _ => { } 849 // them.
850 ty::ReErased => return r,
851
852 // The regions that we expect from borrow checking.
853 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
854
855 ty::ReEmpty(_)
856 | ty::RePlaceholder(_)
857 | ty::ReVar(_)
858 | ty::ReScope(_)
859 | ty::ReClosureBound(_) => {
860 // All of the regions in the type should either have been
861 // erased by writeback, or mapped back to named regions by
862 // borrow checking.
863 bug!("unexpected region kind in opaque type: {:?}", r);
864 }
828 } 865 }
829 866
830 let generics = self.tcx().generics_of(self.opaque_type_def_id); 867 let generics = self.tcx().generics_of(self.opaque_type_def_id);
831 match self.map.get(&r.into()).map(|k| k.unpack()) { 868 match self.map.get(&r.into()).map(|k| k.unpack()) {
832 Some(GenericArgKind::Lifetime(r1)) => r1, 869 Some(GenericArgKind::Lifetime(r1)) => r1,
833 Some(u) => panic!("region mapped to unexpected kind: {:?}", u), 870 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
871 None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
872 self.tcx.lifetimes.re_root_empty
873 }
834 None if generics.parent.is_some() => { 874 None if generics.parent.is_some() => {
835 if !self.map_missing_regions_to_empty && !self.tainted_by_errors { 875 if let Some(hidden_ty) = self.hidden_ty.take() {
836 if let Some(hidden_ty) = self.hidden_ty.take() { 876 unexpected_hidden_region_diagnostic(
837 unexpected_hidden_region_diagnostic( 877 self.tcx,
838 self.tcx, 878 None,
839 None, 879 self.tcx.def_span(self.opaque_type_def_id),
840 self.opaque_type_def_id, 880 hidden_ty,
841 hidden_ty, 881 r,
842 r, 882 )
843 ) 883 .emit();
844 .emit();
845 }
846 } 884 }
847 self.tcx.lifetimes.re_root_empty 885 self.tcx.lifetimes.re_root_empty
848 } 886 }
@@ -860,7 +898,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
860 ) 898 )
861 .emit(); 899 .emit();
862 900
863 self.tcx().mk_region(ty::ReStatic) 901 self.tcx().lifetimes.re_static
864 } 902 }
865 } 903 }
866 } 904 }
diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs
index 34f58ab..824cdfe 100644
--- a/src/librustc/mir/query.rs
+++ b/src/librustc/mir/query.rs
@@ -1,8 +1,10 @@
1//! Values computed by queries that use MIR. 1//! Values computed by queries that use MIR.
2 2
3use crate::ty::{self, Ty}; 3use crate::ty::{self, Ty};
4use rustc_data_structures::fx::FxHashMap;
4use rustc_data_structures::sync::Lrc; 5use rustc_data_structures::sync::Lrc;
5use rustc_hir as hir; 6use rustc_hir as hir;
7use rustc_hir::def_id::DefId;
6use rustc_index::bit_set::BitMatrix; 8use rustc_index::bit_set::BitMatrix;
7use rustc_index::vec::IndexVec; 9use rustc_index::vec::IndexVec;
8use rustc_span::{Span, Symbol}; 10use rustc_span::{Span, Symbol};
@@ -59,8 +61,12 @@ pub struct GeneratorLayout<'tcx> {
59 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>, 61 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
60} 62}
61 63
62#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] 64#[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
63pub struct BorrowCheckResult<'tcx> { 65pub struct BorrowCheckResult<'tcx> {
66 /// All the opaque types that are restricted to concrete types
67 /// by this function. Unlike the value in `TypeckTables`, this has
68 /// unerased regions.
69 pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
64 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, 70 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
65 pub used_mut_upvars: SmallVec<[Field; 8]>, 71 pub used_mut_upvars: SmallVec<[Field; 8]>,
66} 72}
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 11b0798..5e27997 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -125,7 +125,9 @@ rustc_queries! {
125 125
126 /// Fetch the MIR for a given `DefId` right after it's built - this includes 126 /// Fetch the MIR for a given `DefId` right after it's built - this includes
127 /// unreachable code. 127 /// unreachable code.
128 query mir_built(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {} 128 query mir_built(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {
129 desc { "building MIR for" }
130 }
129 131
130 /// Fetch the MIR for a given `DefId` up till the point where it is 132 /// Fetch the MIR for a given `DefId` up till the point where it is
131 /// ready for const evaluation. 133 /// ready for const evaluation.
@@ -345,6 +347,7 @@ rustc_queries! {
345 TypeChecking { 347 TypeChecking {
346 /// The result of unsafety-checking this `DefId`. 348 /// The result of unsafety-checking this `DefId`.
347 query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult { 349 query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult {
350 desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) }
348 cache_on_disk_if { key.is_local() } 351 cache_on_disk_if { key.is_local() }
349 } 352 }
350 353
@@ -414,14 +417,8 @@ rustc_queries! {
414 } 417 }
415 418
416 query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { 419 query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
420 desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
417 cache_on_disk_if { key.is_local() } 421 cache_on_disk_if { key.is_local() }
418 load_cached(tcx, id) {
419 let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
420 .queries.on_disk_cache
421 .try_load_query_result(tcx, id);
422
423 typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
424 }
425 } 422 }
426 query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { 423 query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
427 cache_on_disk_if { key.is_local() } 424 cache_on_disk_if { key.is_local() }
@@ -452,8 +449,13 @@ rustc_queries! {
452 BorrowChecking { 449 BorrowChecking {
453 /// Borrow-checks the function body. If this is a closure, returns 450 /// Borrow-checks the function body. If this is a closure, returns
454 /// additional requirements that the closure's creator must verify. 451 /// additional requirements that the closure's creator must verify.
455 query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> { 452 query mir_borrowck(key: DefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
456 cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) } 453 desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) }
454 cache_on_disk_if(tcx, opt_result) {
455 key.is_local()
456 && (tcx.is_closure(key)
457 || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty()))
458 }
457 } 459 }
458 } 460 }
459 461
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 4a4280b..4546ead 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -138,7 +138,7 @@ impl FlagComputation {
138 } 138 }
139 139
140 &ty::Opaque(_, substs) => { 140 &ty::Opaque(_, substs) => {
141 self.add_flags(TypeFlags::HAS_PROJECTION); 141 self.add_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_OPAQUE);
142 self.add_substs(substs); 142 self.add_substs(substs);
143 } 143 }
144 144
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 1f007b9..3212bc7 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -78,6 +78,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
78 fn has_projections(&self) -> bool { 78 fn has_projections(&self) -> bool {
79 self.has_type_flags(TypeFlags::HAS_PROJECTION) 79 self.has_type_flags(TypeFlags::HAS_PROJECTION)
80 } 80 }
81 fn has_opaque_types(&self) -> bool {
82 self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
83 }
81 fn references_error(&self) -> bool { 84 fn references_error(&self) -> bool {
82 self.has_type_flags(TypeFlags::HAS_TY_ERR) 85 self.has_type_flags(TypeFlags::HAS_TY_ERR)
83 } 86 }
@@ -120,6 +123,10 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
120 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) 123 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
121 } 124 }
122 125
126 fn has_erased_regions(&self) -> bool {
127 self.has_type_flags(TypeFlags::HAS_RE_ERASED)
128 }
129
123 /// True if there are any un-erased free regions. 130 /// True if there are any un-erased free regions.
124 fn has_erasable_regions(&self) -> bool { 131 fn has_erasable_regions(&self) -> bool {
125 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) 132 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b67cab6..45ea05e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -474,10 +474,15 @@ bitflags! {
474 /// if a global bound is safe to evaluate. 474 /// if a global bound is safe to evaluate.
475 const HAS_RE_LATE_BOUND = 1 << 11; 475 const HAS_RE_LATE_BOUND = 1 << 11;
476 476
477 const HAS_TY_PLACEHOLDER = 1 << 12; 477 /// Does this have any `ReErased` regions?
478 const HAS_RE_ERASED = 1 << 12;
478 479
479 const HAS_CT_INFER = 1 << 13; 480 const HAS_TY_PLACEHOLDER = 1 << 13;
480 const HAS_CT_PLACEHOLDER = 1 << 14; 481
482 const HAS_CT_INFER = 1 << 14;
483 const HAS_CT_PLACEHOLDER = 1 << 15;
484 /// Does this have any [Opaque] types.
485 const HAS_TY_OPAQUE = 1 << 16;
481 486
482 const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | 487 const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
483 TypeFlags::HAS_RE_EARLY_BOUND.bits; 488 TypeFlags::HAS_RE_EARLY_BOUND.bits;
@@ -497,9 +502,11 @@ bitflags! {
497 TypeFlags::HAS_FREE_LOCAL_NAMES.bits | 502 TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
498 TypeFlags::KEEP_IN_LOCAL_TCX.bits | 503 TypeFlags::KEEP_IN_LOCAL_TCX.bits |
499 TypeFlags::HAS_RE_LATE_BOUND.bits | 504 TypeFlags::HAS_RE_LATE_BOUND.bits |
505 TypeFlags::HAS_RE_ERASED.bits |
500 TypeFlags::HAS_TY_PLACEHOLDER.bits | 506 TypeFlags::HAS_TY_PLACEHOLDER.bits |
501 TypeFlags::HAS_CT_INFER.bits | 507 TypeFlags::HAS_CT_INFER.bits |
502 TypeFlags::HAS_CT_PLACEHOLDER.bits; 508 TypeFlags::HAS_CT_PLACEHOLDER.bits |
509 TypeFlags::HAS_TY_OPAQUE.bits;
503 } 510 }
504} 511}
505 512
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0718853..02abac9 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1777,7 +1777,9 @@ impl RegionKind {
1777 ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { 1777 ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => {
1778 flags = flags | TypeFlags::HAS_FREE_REGIONS; 1778 flags = flags | TypeFlags::HAS_FREE_REGIONS;
1779 } 1779 }
1780 ty::ReErased => {} 1780 ty::ReErased => {
1781 flags = flags | TypeFlags::HAS_RE_ERASED;
1782 }
1781 ty::ReClosureBound(..) => { 1783 ty::ReClosureBound(..) => {
1782 flags = flags | TypeFlags::HAS_FREE_REGIONS; 1784 flags = flags | TypeFlags::HAS_FREE_REGIONS;
1783 } 1785 }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index db7b8d8..f3c3d04 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -615,7 +615,7 @@ impl<'tcx> TyCtxt<'tcx> {
615 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { 615 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
616 if let ty::Opaque(def_id, substs) = t.kind { 616 if let ty::Opaque(def_id, substs) = t.kind {
617 self.expand_opaque_ty(def_id, substs).unwrap_or(t) 617 self.expand_opaque_ty(def_id, substs).unwrap_or(t)
618 } else if t.has_projections() { 618 } else if t.has_opaque_types() {
619 t.super_fold_with(self) 619 t.super_fold_with(self)
620 } else { 620 } else {
621 t 621 t
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 73a2562..426659f 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -272,7 +272,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
272 let ty = self.lower_ty( 272 let ty = self.lower_ty(
273 t, 273 t,
274 if self.sess.features_untracked().impl_trait_in_bindings { 274 if self.sess.features_untracked().impl_trait_in_bindings {
275 ImplTraitContext::OpaqueTy(None) 275 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
276 } else { 276 } else {
277 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 277 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
278 }, 278 },
@@ -283,7 +283,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
283 let ty = self.lower_ty( 283 let ty = self.lower_ty(
284 t, 284 t,
285 if self.sess.features_untracked().impl_trait_in_bindings { 285 if self.sess.features_untracked().impl_trait_in_bindings {
286 ImplTraitContext::OpaqueTy(None) 286 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
287 } else { 287 } else {
288 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 288 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
289 }, 289 },
@@ -327,8 +327,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
327 } 327 }
328 Some(bounds) => { 328 Some(bounds) => {
329 let ty = hir::OpaqueTy { 329 let ty = hir::OpaqueTy {
330 generics: self.lower_generics(generics, ImplTraitContext::OpaqueTy(None)), 330 generics: self.lower_generics(
331 bounds: self.lower_param_bounds(bounds, ImplTraitContext::OpaqueTy(None)), 331 generics,
332 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
333 ),
334 bounds: self.lower_param_bounds(
335 bounds,
336 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
337 ),
332 impl_trait_fn: None, 338 impl_trait_fn: None,
333 origin: hir::OpaqueTyOrigin::TypeAlias, 339 origin: hir::OpaqueTyOrigin::TypeAlias,
334 }; 340 };
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 618b1e79..99de4b8 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -222,7 +222,7 @@ enum ImplTraitContext<'b, 'a> {
222 /// We optionally store a `DefId` for the parent item here so we can look up necessary 222 /// We optionally store a `DefId` for the parent item here so we can look up necessary
223 /// information later. It is `None` when no information about the context should be stored 223 /// information later. It is `None` when no information about the context should be stored
224 /// (e.g., for consts and statics). 224 /// (e.g., for consts and statics).
225 OpaqueTy(Option<DefId> /* fn def-ID */), 225 OpaqueTy(Option<DefId> /* fn def-ID */, hir::OpaqueTyOrigin),
226 226
227 /// `impl Trait` is not accepted in this position. 227 /// `impl Trait` is not accepted in this position.
228 Disallowed(ImplTraitPosition), 228 Disallowed(ImplTraitPosition),
@@ -248,7 +248,7 @@ impl<'a> ImplTraitContext<'_, 'a> {
248 use self::ImplTraitContext::*; 248 use self::ImplTraitContext::*;
249 match self { 249 match self {
250 Universal(params) => Universal(params), 250 Universal(params) => Universal(params),
251 OpaqueTy(fn_def_id) => OpaqueTy(*fn_def_id), 251 OpaqueTy(fn_def_id, origin) => OpaqueTy(*fn_def_id, *origin),
252 Disallowed(pos) => Disallowed(*pos), 252 Disallowed(pos) => Disallowed(*pos),
253 } 253 }
254 } 254 }
@@ -1010,7 +1010,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1010 // so desugar to 1010 // so desugar to
1011 // 1011 //
1012 // fn foo() -> impl Iterator<Item = impl Debug> 1012 // fn foo() -> impl Iterator<Item = impl Debug>
1013 ImplTraitContext::OpaqueTy(_) => (true, itctx), 1013 ImplTraitContext::OpaqueTy(..) => (true, itctx),
1014 1014
1015 // We are in the argument position, but within a dyn type: 1015 // We are in the argument position, but within a dyn type:
1016 // 1016 //
@@ -1019,7 +1019,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1019 // so desugar to 1019 // so desugar to
1020 // 1020 //
1021 // fn foo(x: dyn Iterator<Item = impl Debug>) 1021 // fn foo(x: dyn Iterator<Item = impl Debug>)
1022 ImplTraitContext::Universal(_) if self.is_in_dyn_type => (true, itctx), 1022 ImplTraitContext::Universal(..) if self.is_in_dyn_type => (true, itctx),
1023 1023
1024 // In `type Foo = dyn Iterator<Item: Debug>` we desugar to 1024 // In `type Foo = dyn Iterator<Item: Debug>` we desugar to
1025 // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the 1025 // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
@@ -1028,7 +1028,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1028 // 1028 //
1029 // FIXME: this is only needed until `impl Trait` is allowed in type aliases. 1029 // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
1030 ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { 1030 ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
1031 (true, ImplTraitContext::OpaqueTy(None)) 1031 (true, ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc))
1032 } 1032 }
1033 1033
1034 // We are in the parameter position, but not within a dyn type: 1034 // We are in the parameter position, but not within a dyn type:
@@ -1269,8 +1269,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1269 TyKind::ImplTrait(def_node_id, ref bounds) => { 1269 TyKind::ImplTrait(def_node_id, ref bounds) => {
1270 let span = t.span; 1270 let span = t.span;
1271 match itctx { 1271 match itctx {
1272 ImplTraitContext::OpaqueTy(fn_def_id) => { 1272 ImplTraitContext::OpaqueTy(fn_def_id, origin) => {
1273 self.lower_opaque_impl_trait(span, fn_def_id, def_node_id, |this| { 1273 self.lower_opaque_impl_trait(span, fn_def_id, origin, def_node_id, |this| {
1274 this.lower_param_bounds(bounds, itctx) 1274 this.lower_param_bounds(bounds, itctx)
1275 }) 1275 })
1276 } 1276 }
@@ -1349,6 +1349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1349 &mut self, 1349 &mut self,
1350 span: Span, 1350 span: Span,
1351 fn_def_id: Option<DefId>, 1351 fn_def_id: Option<DefId>,
1352 origin: hir::OpaqueTyOrigin,
1352 opaque_ty_node_id: NodeId, 1353 opaque_ty_node_id: NodeId,
1353 lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, 1354 lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
1354 ) -> hir::TyKind<'hir> { 1355 ) -> hir::TyKind<'hir> {
@@ -1390,7 +1391,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1390 }, 1391 },
1391 bounds: hir_bounds, 1392 bounds: hir_bounds,
1392 impl_trait_fn: fn_def_id, 1393 impl_trait_fn: fn_def_id,
1393 origin: hir::OpaqueTyOrigin::FnReturn, 1394 origin,
1394 }; 1395 };
1395 1396
1396 trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); 1397 trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
@@ -1622,7 +1623,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1622 self.lower_ty( 1623 self.lower_ty(
1623 t, 1624 t,
1624 if self.sess.features_untracked().impl_trait_in_bindings { 1625 if self.sess.features_untracked().impl_trait_in_bindings {
1625 ImplTraitContext::OpaqueTy(Some(parent_def_id)) 1626 ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc)
1626 } else { 1627 } else {
1627 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 1628 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
1628 }, 1629 },
@@ -1722,14 +1723,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1722 ) 1723 )
1723 } else { 1724 } else {
1724 match decl.output { 1725 match decl.output {
1725 FunctionRetTy::Ty(ref ty) => match in_band_ty_params { 1726 FunctionRetTy::Ty(ref ty) => {
1726 Some((def_id, _)) if impl_trait_return_allow => hir::FunctionRetTy::Return( 1727 let context = match in_band_ty_params {
1727 self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))), 1728 Some((def_id, _)) if impl_trait_return_allow => {
1728 ), 1729 ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn)
1729 _ => hir::FunctionRetTy::Return( 1730 }
1730 self.lower_ty(ty, ImplTraitContext::disallowed()), 1731 _ => ImplTraitContext::disallowed(),
1731 ), 1732 };
1732 }, 1733 hir::FunctionRetTy::Return(self.lower_ty(ty, context))
1734 }
1733 FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span), 1735 FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span),
1734 } 1736 }
1735 }; 1737 };
@@ -1957,7 +1959,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1957 ) -> hir::GenericBound<'hir> { 1959 ) -> hir::GenericBound<'hir> {
1958 // Compute the `T` in `Future<Output = T>` from the return type. 1960 // Compute the `T` in `Future<Output = T>` from the return type.
1959 let output_ty = match output { 1961 let output_ty = match output {
1960 FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))), 1962 FunctionRetTy::Ty(ty) => {
1963 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
1964 // `impl Future` opaque type that `async fn` implicitly
1965 // generates.
1966 let context =
1967 ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn);
1968 self.lower_ty(ty, context)
1969 }
1961 FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), 1970 FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
1962 }; 1971 };
1963 1972
@@ -2102,9 +2111,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2102 } 2111 }
2103 2112
2104 let kind = hir::GenericParamKind::Type { 2113 let kind = hir::GenericParamKind::Type {
2105 default: default 2114 default: default.as_ref().map(|x| {
2106 .as_ref() 2115 self.lower_ty(
2107 .map(|x| self.lower_ty(x, ImplTraitContext::OpaqueTy(None))), 2116 x,
2117 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
2118 )
2119 }),
2108 synthetic: param 2120 synthetic: param
2109 .attrs 2121 .attrs
2110 .iter() 2122 .iter()
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 80b3792..07a2c48 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1990,6 +1990,8 @@ pub enum OpaqueTyOrigin {
1990 FnReturn, 1990 FnReturn,
1991 /// `async fn` 1991 /// `async fn`
1992 AsyncFn, 1992 AsyncFn,
1993 /// Impl trait in bindings, consts, statics, bounds.
1994 Misc,
1993} 1995}
1994 1996
1995/// The various kinds of types recognized by the compiler. 1997/// The various kinds of types recognized by the compiler.
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 0e040ec..b393d4b 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -6,7 +6,6 @@ use rustc::infer::{
6use rustc::mir::ConstraintCategory; 6use rustc::mir::ConstraintCategory;
7use rustc::ty::{self, RegionVid, Ty}; 7use rustc::ty::{self, RegionVid, Ty};
8use rustc_errors::{Applicability, DiagnosticBuilder}; 8use rustc_errors::{Applicability, DiagnosticBuilder};
9use rustc_hir::def_id::DefId;
10use rustc_span::symbol::kw; 9use rustc_span::symbol::kw;
11use rustc_span::Span; 10use rustc_span::Span;
12 11
@@ -58,8 +57,8 @@ crate enum RegionErrorKind<'tcx> {
58 57
59 /// An unexpected hidden region for an opaque type. 58 /// An unexpected hidden region for an opaque type.
60 UnexpectedHiddenRegion { 59 UnexpectedHiddenRegion {
61 /// The def id of the opaque type. 60 /// The span for the member constraint.
62 opaque_type_def_id: DefId, 61 span: Span,
63 /// The hidden type. 62 /// The hidden type.
64 hidden_ty: Ty<'tcx>, 63 hidden_ty: Ty<'tcx>,
65 /// The unexpected region. 64 /// The unexpected region.
@@ -194,18 +193,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
194 } 193 }
195 } 194 }
196 195
197 RegionErrorKind::UnexpectedHiddenRegion { 196 RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
198 opaque_type_def_id,
199 hidden_ty,
200 member_region,
201 } => {
202 let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); 197 let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
198 let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
199 let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
203 opaque_types::unexpected_hidden_region_diagnostic( 200 opaque_types::unexpected_hidden_region_diagnostic(
204 self.infcx.tcx, 201 self.infcx.tcx,
205 Some(region_scope_tree), 202 Some(region_scope_tree),
206 opaque_type_def_id, 203 span,
207 hidden_ty, 204 named_ty,
208 member_region, 205 named_region,
209 ) 206 )
210 .buffer(&mut self.errors_buffer); 207 .buffer(&mut self.errors_buffer);
211 } 208 }
@@ -588,6 +585,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
588 { 585 {
589 found = true; 586 found = true;
590 break; 587 break;
588 } else {
589 // If there's already a lifetime bound, don't
590 // suggest anything.
591 return;
591 } 592 }
592 } 593 }
593 } 594 }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 941534e..f9db62e 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -90,7 +90,7 @@ pub fn provide(providers: &mut Providers<'_>) {
90 *providers = Providers { mir_borrowck, ..*providers }; 90 *providers = Providers { mir_borrowck, ..*providers };
91} 91}
92 92
93fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { 93fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> &BorrowCheckResult<'_> {
94 let (input_body, promoted) = tcx.mir_validated(def_id); 94 let (input_body, promoted) = tcx.mir_validated(def_id);
95 debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); 95 debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id));
96 96
@@ -101,7 +101,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> {
101 }); 101 });
102 debug!("mir_borrowck done"); 102 debug!("mir_borrowck done");
103 103
104 opt_closure_req 104 tcx.arena.alloc(opt_closure_req)
105} 105}
106 106
107fn do_mir_borrowck<'a, 'tcx>( 107fn do_mir_borrowck<'a, 'tcx>(
@@ -136,6 +136,9 @@ fn do_mir_borrowck<'a, 'tcx>(
136 136
137 // Gather the upvars of a closure, if any. 137 // Gather the upvars of a closure, if any.
138 let tables = tcx.typeck_tables_of(def_id); 138 let tables = tcx.typeck_tables_of(def_id);
139 if tables.tainted_by_errors {
140 infcx.set_tainted_by_errors();
141 }
139 let upvars: Vec<_> = tables 142 let upvars: Vec<_> = tables
140 .upvar_list 143 .upvar_list
141 .get(&def_id) 144 .get(&def_id)
@@ -195,27 +198,40 @@ fn do_mir_borrowck<'a, 'tcx>(
195 Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); 198 Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
196 199
197 // Compute non-lexical lifetimes. 200 // Compute non-lexical lifetimes.
198 let nll::NllOutput { regioncx, polonius_output, opt_closure_req, nll_errors } = 201 let nll::NllOutput {
199 nll::compute_regions( 202 regioncx,
200 infcx, 203 opaque_type_values,
201 def_id, 204 polonius_output,
202 free_regions, 205 opt_closure_req,
203 body, 206 nll_errors,
204 &promoted, 207 } = nll::compute_regions(
205 location_table, 208 infcx,
206 param_env, 209 def_id,
207 &mut flow_inits, 210 free_regions,
208 &mdpe.move_data, 211 body,
209 &borrow_set, 212 &promoted,
210 ); 213 location_table,
214 param_env,
215 &mut flow_inits,
216 &mdpe.move_data,
217 &borrow_set,
218 );
211 219
212 // Dump MIR results into a file, if that is enabled. This let us 220 // Dump MIR results into a file, if that is enabled. This let us
213 // write unit-tests, as well as helping with debugging. 221 // write unit-tests, as well as helping with debugging.
214 nll::dump_mir_results(infcx, MirSource::item(def_id), &body, &regioncx, &opt_closure_req); 222 nll::dump_mir_results(infcx, MirSource::item(def_id), &body, &regioncx, &opt_closure_req);
215 223
216 // We also have a `#[rustc_nll]` annotation that causes us to dump 224 // We also have a `#[rustc_regions]` annotation that causes us to dump
217 // information. 225 // information.
218 nll::dump_annotation(infcx, &body, def_id, &regioncx, &opt_closure_req, &mut errors_buffer); 226 nll::dump_annotation(
227 infcx,
228 &body,
229 def_id,
230 &regioncx,
231 &opt_closure_req,
232 &opaque_type_values,
233 &mut errors_buffer,
234 );
219 235
220 // The various `flow_*` structures can be large. We drop `flow_inits` here 236 // The various `flow_*` structures can be large. We drop `flow_inits` here
221 // so it doesn't overlap with the others below. This reduces peak memory 237 // so it doesn't overlap with the others below. This reduces peak memory
@@ -389,6 +405,7 @@ fn do_mir_borrowck<'a, 'tcx>(
389 } 405 }
390 406
391 let result = BorrowCheckResult { 407 let result = BorrowCheckResult {
408 concrete_opaque_types: opaque_type_values,
392 closure_requirements: opt_closure_req, 409 closure_requirements: opt_closure_req,
393 used_mut_upvars: mbcx.used_mut_upvars, 410 used_mut_upvars: mbcx.used_mut_upvars,
394 }; 411 };
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index a71dfc9..101d185 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -6,6 +6,7 @@ use rustc::mir::{
6 Location, Promoted, ReadOnlyBodyAndCache, 6 Location, Promoted, ReadOnlyBodyAndCache,
7}; 7};
8use rustc::ty::{self, RegionKind, RegionVid}; 8use rustc::ty::{self, RegionKind, RegionVid};
9use rustc_data_structures::fx::FxHashMap;
9use rustc_errors::Diagnostic; 10use rustc_errors::Diagnostic;
10use rustc_hir::def_id::DefId; 11use rustc_hir::def_id::DefId;
11use rustc_index::vec::IndexVec; 12use rustc_index::vec::IndexVec;
@@ -46,6 +47,7 @@ crate type PoloniusOutput = Output<RustcFacts>;
46/// closure requirements to propagate, and any generated errors. 47/// closure requirements to propagate, and any generated errors.
47crate struct NllOutput<'tcx> { 48crate struct NllOutput<'tcx> {
48 pub regioncx: RegionInferenceContext<'tcx>, 49 pub regioncx: RegionInferenceContext<'tcx>,
50 pub opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
49 pub polonius_output: Option<Rc<PoloniusOutput>>, 51 pub polonius_output: Option<Rc<PoloniusOutput>>,
50 pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>, 52 pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
51 pub nll_errors: RegionErrors<'tcx>, 53 pub nll_errors: RegionErrors<'tcx>,
@@ -160,20 +162,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
160 let elements = &Rc::new(RegionValueElements::new(&body)); 162 let elements = &Rc::new(RegionValueElements::new(&body));
161 163
162 // Run the MIR type-checker. 164 // Run the MIR type-checker.
163 let MirTypeckResults { constraints, universal_region_relations } = type_check::type_check( 165 let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
164 infcx, 166 type_check::type_check(
165 param_env, 167 infcx,
166 body, 168 param_env,
167 promoted, 169 body,
168 def_id, 170 promoted,
169 &universal_regions, 171 def_id,
170 location_table, 172 &universal_regions,
171 borrow_set, 173 location_table,
172 &mut all_facts, 174 borrow_set,
173 flow_inits, 175 &mut all_facts,
174 move_data, 176 flow_inits,
175 elements, 177 move_data,
176 ); 178 elements,
179 );
177 180
178 if let Some(all_facts) = &mut all_facts { 181 if let Some(all_facts) = &mut all_facts {
179 let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation"); 182 let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
@@ -279,8 +282,16 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
279 let (closure_region_requirements, nll_errors) = 282 let (closure_region_requirements, nll_errors) =
280 regioncx.solve(infcx, &body, def_id, polonius_output.clone()); 283 regioncx.solve(infcx, &body, def_id, polonius_output.clone());
281 284
285 if !nll_errors.is_empty() {
286 // Suppress unhelpful extra errors in `infer_opaque_types`.
287 infcx.set_tainted_by_errors();
288 }
289
290 let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
291
282 NllOutput { 292 NllOutput {
283 regioncx, 293 regioncx,
294 opaque_type_values: remapped_opaque_tys,
284 polonius_output, 295 polonius_output,
285 opt_closure_req: closure_region_requirements, 296 opt_closure_req: closure_region_requirements,
286 nll_errors, 297 nll_errors,
@@ -344,6 +355,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
344 mir_def_id: DefId, 355 mir_def_id: DefId,
345 regioncx: &RegionInferenceContext<'tcx>, 356 regioncx: &RegionInferenceContext<'tcx>,
346 closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, 357 closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
358 opaque_type_values: &FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
347 errors_buffer: &mut Vec<Diagnostic>, 359 errors_buffer: &mut Vec<Diagnostic>,
348) { 360) {
349 let tcx = infcx.tcx; 361 let tcx = infcx.tcx;
@@ -359,7 +371,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
359 // viewing the intraprocedural state, the -Zdump-mir output is 371 // viewing the intraprocedural state, the -Zdump-mir output is
360 // better. 372 // better.
361 373
362 if let Some(closure_region_requirements) = closure_region_requirements { 374 let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
363 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements"); 375 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements");
364 376
365 regioncx.annotate(tcx, &mut err); 377 regioncx.annotate(tcx, &mut err);
@@ -377,13 +389,19 @@ pub(super) fn dump_annotation<'a, 'tcx>(
377 }) 389 })
378 .unwrap(); 390 .unwrap();
379 391
380 err.buffer(errors_buffer); 392 err
381 } else { 393 } else {
382 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements"); 394 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements");
383 regioncx.annotate(tcx, &mut err); 395 regioncx.annotate(tcx, &mut err);
384 396
385 err.buffer(errors_buffer); 397 err
398 };
399
400 if !opaque_type_values.is_empty() {
401 err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values));
386 } 402 }
403
404 err.buffer(errors_buffer);
387} 405}
388 406
389fn for_each_region_constraint( 407fn for_each_region_constraint(
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 6abca48..192e470 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -12,8 +12,6 @@ use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
12use rustc_data_structures::binary_search_util; 12use rustc_data_structures::binary_search_util;
13use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 13use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14use rustc_data_structures::graph::scc::Sccs; 14use rustc_data_structures::graph::scc::Sccs;
15use rustc_data_structures::graph::vec_graph::VecGraph;
16use rustc_data_structures::graph::WithSuccessors;
17use rustc_hir::def_id::DefId; 15use rustc_hir::def_id::DefId;
18use rustc_index::bit_set::BitSet; 16use rustc_index::bit_set::BitSet;
19use rustc_index::vec::IndexVec; 17use rustc_index::vec::IndexVec;
@@ -26,6 +24,7 @@ use crate::borrow_check::{
26 diagnostics::{RegionErrorKind, RegionErrors}, 24 diagnostics::{RegionErrorKind, RegionErrors},
27 member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, 25 member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
28 nll::{PoloniusOutput, ToRegionVid}, 26 nll::{PoloniusOutput, ToRegionVid},
27 region_infer::reverse_sccs::ReverseSccGraph,
29 region_infer::values::{ 28 region_infer::values::{
30 LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, 29 LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
31 ToElementIndex, 30 ToElementIndex,
@@ -36,6 +35,8 @@ use crate::borrow_check::{
36 35
37mod dump_mir; 36mod dump_mir;
38mod graphviz; 37mod graphviz;
38mod opaque_types;
39mod reverse_sccs;
39 40
40pub mod values; 41pub mod values;
41 42
@@ -65,9 +66,10 @@ pub struct RegionInferenceContext<'tcx> {
65 /// compute the values of each region. 66 /// compute the values of each region.
66 constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>, 67 constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
67 68
68 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` 69 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
69 /// exists if `B: A`. Computed lazilly. 70 /// `B: A`. This is used to compute the universal regions that are required
70 rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>, 71 /// to outlive a given SCC. Computed lazily.
72 rev_scc_graph: Option<Rc<ReverseSccGraph>>,
71 73
72 /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. 74 /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
73 member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>, 75 member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
@@ -287,7 +289,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
287 constraints, 289 constraints,
288 constraint_graph, 290 constraint_graph,
289 constraint_sccs, 291 constraint_sccs,
290 rev_constraint_graph: None, 292 rev_scc_graph: None,
291 member_constraints, 293 member_constraints,
292 member_constraints_applied: Vec::new(), 294 member_constraints_applied: Vec::new(),
293 closure_bounds_mapping, 295 closure_bounds_mapping,
@@ -510,7 +512,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
510 self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer); 512 self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
511 } 513 }
512 514
513 self.check_member_constraints(infcx, &mut errors_buffer); 515 if errors_buffer.is_empty() {
516 self.check_member_constraints(infcx, &mut errors_buffer);
517 }
514 518
515 let outlives_requirements = outlives_requirements.unwrap_or(vec![]); 519 let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
516 520
@@ -677,15 +681,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
677 // free region that must outlive the member region `R0` (`UB: 681 // free region that must outlive the member region `R0` (`UB:
678 // R0`). Therefore, we need only keep an option `O` if `UB: O` 682 // R0`). Therefore, we need only keep an option `O` if `UB: O`
679 // for all UB. 683 // for all UB.
680 if choice_regions.len() > 1 { 684 let rev_scc_graph = self.reverse_scc_graph();
681 let universal_region_relations = self.universal_region_relations.clone(); 685 let universal_region_relations = &self.universal_region_relations;
682 let rev_constraint_graph = self.rev_constraint_graph(); 686 for ub in rev_scc_graph.upper_bounds(scc) {
683 for ub in self.upper_bounds(scc, &rev_constraint_graph) { 687 debug!("apply_member_constraint: ub={:?}", ub);
684 debug!("apply_member_constraint: ub={:?}", ub); 688 choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
685 choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
686 }
687 debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
688 } 689 }
690 debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
689 691
690 // If we ruled everything out, we're done. 692 // If we ruled everything out, we're done.
691 if choice_regions.is_empty() { 693 if choice_regions.is_empty() {
@@ -741,32 +743,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
741 } 743 }
742 } 744 }
743 745
744 /// Compute and return the reverse SCC-based constraint graph (lazilly).
745 fn upper_bounds(
746 &'a mut self,
747 scc0: ConstraintSccIndex,
748 rev_constraint_graph: &'a VecGraph<ConstraintSccIndex>,
749 ) -> impl Iterator<Item = RegionVid> + 'a {
750 let scc_values = &self.scc_values;
751 let mut duplicates = FxHashSet::default();
752 rev_constraint_graph
753 .depth_first_search(scc0)
754 .skip(1)
755 .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1))
756 .filter(move |&r| duplicates.insert(r))
757 }
758
759 /// Compute and return the reverse SCC-based constraint graph (lazilly).
760 fn rev_constraint_graph(&mut self) -> Rc<VecGraph<ConstraintSccIndex>> {
761 if let Some(g) = &self.rev_constraint_graph {
762 return g.clone();
763 }
764
765 let rev_graph = Rc::new(self.constraint_sccs.reverse());
766 self.rev_constraint_graph = Some(rev_graph.clone());
767 rev_graph
768 }
769
770 /// Returns `true` if all the elements in the value of `scc_b` are nameable 746 /// Returns `true` if all the elements in the value of `scc_b` are nameable
771 /// in `scc_a`. Used during constraint propagation, and only once 747 /// in `scc_a`. Used during constraint propagation, and only once
772 /// the value of `scc_b` has been computed. 748 /// the value of `scc_b` has been computed.
@@ -1603,7 +1579,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1603 // If not, report an error. 1579 // If not, report an error.
1604 let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid)); 1580 let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
1605 errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion { 1581 errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
1606 opaque_type_def_id: m_c.opaque_type_def_id, 1582 span: m_c.definition_span,
1607 hidden_ty: m_c.hidden_ty, 1583 hidden_ty: m_c.hidden_ty,
1608 member_region, 1584 member_region,
1609 }); 1585 });
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
new file mode 100644
index 0000000..52d54f7
--- /dev/null
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -0,0 +1,149 @@
1use rustc::infer::InferCtxt;
2use rustc::ty::{self, TyCtxt, TypeFoldable};
3use rustc_data_structures::fx::FxHashMap;
4use rustc_hir::def_id::DefId;
5use rustc_span::Span;
6
7use super::RegionInferenceContext;
8
9impl<'tcx> RegionInferenceContext<'tcx> {
10 /// Resolve any opaque types that were encountered while borrow checking
11 /// this item. This is then used to get the type in the `type_of` query.
12 ///
13 /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`.
14 /// This is lowered to give HIR something like
15 ///
16 /// type f<'a>::_Return<'_a> = impl Sized + '_a;
17 /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x }
18 ///
19 /// When checking the return type record the type from the return and the
20 /// type used in the return value. In this case they might be `_Return<'1>`
21 /// and `&'2 i32` respectively.
22 ///
23 /// Once we to this method, we have completed region inference and want to
24 /// call `infer_opaque_definition_from_instantiation` to get the inferred
25 /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation`
26 /// compares lifetimes directly, so we need to map the inference variables
27 /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`.
28 ///
29 /// First we map all the lifetimes in the concrete type to an equal
30 /// universal region that occurs in the concrete type's substs, in this case
31 /// this would result in `&'1 i32`. We only consider regions in the substs
32 /// in case there is an equal region that does not. For example, this should
33 /// be allowed:
34 /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
35 ///
36 /// Then we map the regions in both the type and the subst to their
37 /// `external_name` giving `concrete_type = &'a i32`,
38 /// `substs = ['static, 'a]`. This will then allow
39 /// `infer_opaque_definition_from_instantiation` to determine that
40 /// `_Return<'_a> = &'_a i32`.
41 ///
42 /// There's a slight complication around closures. Given
43 /// `fn f<'a: 'a>() { || {} }` the closure's type is something like
44 /// `f::<'a>::{{closure}}`. The region parameter from f is essentially
45 /// ignored by type checking so ends up being inferred to an empty region.
46 /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
47 /// which has no `external_name` in which case we use `'empty` as the
48 /// region to pass to `infer_opaque_definition_from_instantiation`.
49 pub(in crate::borrow_check) fn infer_opaque_types(
50 &self,
51 infcx: &InferCtxt<'_, 'tcx>,
52 opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
53 span: Span,
54 ) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
55 opaque_ty_decls
56 .into_iter()
57 .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
58 debug!(
59 "infer_opaque_types(concrete_type = {:?}, substs = {:?})",
60 concrete_type, substs
61 );
62
63 let mut subst_regions = vec![self.universal_regions.fr_static];
64 let universal_substs =
65 infcx.tcx.fold_regions(&substs, &mut false, |region, _| match *region {
66 ty::ReVar(vid) => {
67 subst_regions.push(vid);
68 self.definitions[vid].external_name.unwrap_or_else(|| {
69 infcx.tcx.sess.delay_span_bug(
70 span,
71 "opaque type with non-universal region substs",
72 );
73 infcx.tcx.lifetimes.re_static
74 })
75 }
76 // We don't fold regions in the predicates of opaque
77 // types to `ReVar`s. This means that in a case like
78 //
79 // fn f<'a: 'a>() -> impl Iterator<Item = impl Sized>
80 //
81 // The inner opaque type has `'static` in its substs.
82 ty::ReStatic => region,
83 _ => {
84 infcx.tcx.sess.delay_span_bug(
85 span,
86 &format!("unexpected concrete region in borrowck: {:?}", region),
87 );
88 region
89 }
90 });
91
92 subst_regions.sort();
93 subst_regions.dedup();
94
95 let universal_concrete_type =
96 infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match *region {
97 ty::ReVar(vid) => subst_regions
98 .iter()
99 .find(|ur_vid| self.eval_equal(vid, **ur_vid))
100 .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
101 .unwrap_or(infcx.tcx.lifetimes.re_root_empty),
102 ty::ReLateBound(..) => region,
103 _ => {
104 infcx.tcx.sess.delay_span_bug(
105 span,
106 &format!("unexpected concrete region in borrowck: {:?}", region),
107 );
108 region
109 }
110 });
111
112 debug!(
113 "infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
114 universal_concrete_type, universal_substs
115 );
116
117 let remapped_type = infcx.infer_opaque_definition_from_instantiation(
118 opaque_def_id,
119 universal_substs,
120 universal_concrete_type,
121 span,
122 );
123 (
124 opaque_def_id,
125 ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
126 )
127 })
128 .collect()
129 }
130
131 /// Map the regions in the type to named regions. This is similar to what
132 /// `infer_opaque_types` does, but can infer any universal region, not only
133 /// ones from the substs for the opaque type. It also doesn't double check
134 /// that the regions produced are in fact equal to the named region they are
135 /// replaced with. This is fine because this function is only to improve the
136 /// region names in error messages.
137 pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
138 where
139 T: TypeFoldable<'tcx>,
140 {
141 tcx.fold_regions(&ty, &mut false, |region, _| match *region {
142 ty::ReVar(vid) => {
143 let upper_bound = self.universal_upper_bound(vid);
144 self.definitions[upper_bound].external_name.unwrap_or(region)
145 }
146 _ => region,
147 })
148 }
149}
diff --git a/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs
new file mode 100644
index 0000000..4b8357b
--- /dev/null
+++ b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs
@@ -0,0 +1,68 @@
1use crate::borrow_check::constraints::ConstraintSccIndex;
2use crate::borrow_check::RegionInferenceContext;
3use itertools::Itertools;
4use rustc::ty::RegionVid;
5use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6use rustc_data_structures::graph::vec_graph::VecGraph;
7use rustc_data_structures::graph::WithSuccessors;
8use std::ops::Range;
9use std::rc::Rc;
10
11crate struct ReverseSccGraph {
12 graph: VecGraph<ConstraintSccIndex>,
13 /// For each SCC, the range of `universal_regions` that use that SCC as
14 /// their value.
15 scc_regions: FxHashMap<ConstraintSccIndex, Range<usize>>,
16 /// All of the universal regions, in grouped so that `scc_regions` can
17 /// index into here.
18 universal_regions: Vec<RegionVid>,
19}
20
21impl ReverseSccGraph {
22 /// Find all universal regions that are required to outlive the given SCC.
23 pub(super) fn upper_bounds<'a>(
24 &'a self,
25 scc0: ConstraintSccIndex,
26 ) -> impl Iterator<Item = RegionVid> + 'a {
27 let mut duplicates = FxHashSet::default();
28 self.graph
29 .depth_first_search(scc0)
30 .flat_map(move |scc1| {
31 self.scc_regions
32 .get(&scc1)
33 .map_or(&[][..], |range| &self.universal_regions[range.clone()])
34 })
35 .copied()
36 .filter(move |r| duplicates.insert(*r))
37 }
38}
39
40impl RegionInferenceContext<'_> {
41 /// Compute and return the reverse SCC-based constraint graph (lazily).
42 pub(super) fn reverse_scc_graph(&mut self) -> Rc<ReverseSccGraph> {
43 if let Some(g) = &self.rev_scc_graph {
44 return g.clone();
45 }
46
47 let graph = self.constraint_sccs.reverse();
48 let mut paired_scc_regions = self
49 .universal_regions
50 .universal_regions()
51 .map(|region| (self.constraint_sccs.scc(region), region))
52 .collect_vec();
53 paired_scc_regions.sort();
54 let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
55
56 let mut scc_regions = FxHashMap::default();
57 let mut start = 0;
58 for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) {
59 let group_size = group.into_iter().count();
60 scc_regions.insert(scc, start..start + group_size);
61 start += group_size;
62 }
63
64 let rev_graph = Rc::new(ReverseSccGraph { graph, scc_regions, universal_regions });
65 self.rev_scc_graph = Some(rev_graph.clone());
66 rev_graph
67 }
68}
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 5dab064..88fe6d1 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -6,6 +6,7 @@ use std::{fmt, iter, mem};
6use either::Either; 6use either::Either;
7 7
8use rustc::infer::canonical::QueryRegionConstraints; 8use rustc::infer::canonical::QueryRegionConstraints;
9use rustc::infer::opaque_types::GenerateMemberConstraints;
9use rustc::infer::outlives::env::RegionBoundPairs; 10use rustc::infer::outlives::env::RegionBoundPairs;
10use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 11use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
11use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; 12use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
@@ -158,7 +159,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
158 constraints: &mut constraints, 159 constraints: &mut constraints,
159 }; 160 };
160 161
161 type_check_internal( 162 let opaque_type_values = type_check_internal(
162 infcx, 163 infcx,
163 mir_def_id, 164 mir_def_id,
164 param_env, 165 param_env,
@@ -173,10 +174,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
173 liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); 174 liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
174 175
175 translate_outlives_facts(&mut cx); 176 translate_outlives_facts(&mut cx);
177 cx.opaque_type_values
176 }, 178 },
177 ); 179 );
178 180
179 MirTypeckResults { constraints, universal_region_relations } 181 MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
180} 182}
181 183
182fn type_check_internal<'a, 'tcx, R>( 184fn type_check_internal<'a, 'tcx, R>(
@@ -189,7 +191,7 @@ fn type_check_internal<'a, 'tcx, R>(
189 implicit_region_bound: ty::Region<'tcx>, 191 implicit_region_bound: ty::Region<'tcx>,
190 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, 192 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
191 universal_region_relations: &'a UniversalRegionRelations<'tcx>, 193 universal_region_relations: &'a UniversalRegionRelations<'tcx>,
192 mut extra: impl FnMut(&mut TypeChecker<'a, 'tcx>) -> R, 194 extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
193) -> R { 195) -> R {
194 let mut checker = TypeChecker::new( 196 let mut checker = TypeChecker::new(
195 infcx, 197 infcx,
@@ -212,7 +214,7 @@ fn type_check_internal<'a, 'tcx, R>(
212 checker.typeck_mir(body); 214 checker.typeck_mir(body);
213 } 215 }
214 216
215 extra(&mut checker) 217 extra(checker)
216} 218}
217 219
218fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { 220fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
@@ -799,6 +801,7 @@ struct TypeChecker<'a, 'tcx> {
799 reported_errors: FxHashSet<(Ty<'tcx>, Span)>, 801 reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
800 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, 802 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
801 universal_region_relations: &'a UniversalRegionRelations<'tcx>, 803 universal_region_relations: &'a UniversalRegionRelations<'tcx>,
804 opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
802} 805}
803 806
804struct BorrowCheckContext<'a, 'tcx> { 807struct BorrowCheckContext<'a, 'tcx> {
@@ -812,6 +815,7 @@ struct BorrowCheckContext<'a, 'tcx> {
812crate struct MirTypeckResults<'tcx> { 815crate struct MirTypeckResults<'tcx> {
813 crate constraints: MirTypeckRegionConstraints<'tcx>, 816 crate constraints: MirTypeckRegionConstraints<'tcx>,
814 crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>, 817 crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
818 crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
815} 819}
816 820
817/// A collection of region constraints that must be satisfied for the 821/// A collection of region constraints that must be satisfied for the
@@ -958,6 +962,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
958 borrowck_context, 962 borrowck_context,
959 reported_errors: Default::default(), 963 reported_errors: Default::default(),
960 universal_region_relations, 964 universal_region_relations,
965 opaque_type_values: FxHashMap::default(),
961 }; 966 };
962 checker.check_user_type_annotations(); 967 checker.check_user_type_annotations();
963 checker 968 checker
@@ -1191,10 +1196,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1191 anon_ty={:?})", 1196 anon_ty={:?})",
1192 revealed_ty, anon_ty 1197 revealed_ty, anon_ty
1193 ); 1198 );
1199
1200 // Fast path for the common case.
1201 if !anon_ty.has_opaque_types() {
1202 if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
1203 span_mirbug!(
1204 self,
1205 locations,
1206 "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
1207 revealed_ty,
1208 anon_ty,
1209 terr
1210 );
1211 }
1212 return Ok(());
1213 }
1214
1194 let infcx = self.infcx; 1215 let infcx = self.infcx;
1195 let tcx = infcx.tcx; 1216 let tcx = infcx.tcx;
1196 let param_env = self.param_env; 1217 let param_env = self.param_env;
1197 let body = self.body; 1218 let body = self.body;
1219 let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types;
1220 let mut opaque_type_values = Vec::new();
1221
1198 debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id); 1222 debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
1199 let opaque_type_map = self.fully_perform_op( 1223 let opaque_type_map = self.fully_perform_op(
1200 locations, 1224 locations,
@@ -1219,6 +1243,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1219 revealed_ty={:?}", 1243 revealed_ty={:?}",
1220 output_ty, opaque_type_map, revealed_ty 1244 output_ty, opaque_type_map, revealed_ty
1221 ); 1245 );
1246 // Make sure that the inferred types are well-formed. I'm
1247 // not entirely sure this is needed (the HIR type check
1248 // didn't do this) but it seems sensible to prevent opaque
1249 // types hiding ill-formed types.
1250 obligations.obligations.push(traits::Obligation::new(
1251 ObligationCause::dummy(),
1252 param_env,
1253 ty::Predicate::WellFormed(revealed_ty),
1254 ));
1222 obligations.add( 1255 obligations.add(
1223 infcx 1256 infcx
1224 .at(&ObligationCause::dummy(), param_env) 1257 .at(&ObligationCause::dummy(), param_env)
@@ -1226,47 +1259,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1226 ); 1259 );
1227 1260
1228 for (&opaque_def_id, opaque_decl) in &opaque_type_map { 1261 for (&opaque_def_id, opaque_decl) in &opaque_type_map {
1229 let opaque_defn_ty = tcx.type_of(opaque_def_id); 1262 let resolved_ty = infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty);
1230 let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); 1263 let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind {
1231 let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty); 1264 def_id == opaque_def_id
1232 let concrete_is_opaque = infcx 1265 } else {
1233 .resolve_vars_if_possible(&opaque_decl.concrete_ty) 1266 false
1234 .is_impl_trait(); 1267 };
1268 let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) {
1269 None => {
1270 if !concrete_is_opaque {
1271 tcx.sess.delay_span_bug(
1272 body.span,
1273 &format!(
1274 "Non-defining use of {:?} with revealed type",
1275 opaque_def_id,
1276 ),
1277 );
1278 }
1279 continue;
1280 }
1281 Some(opaque_defn_ty) => opaque_defn_ty,
1282 };
1283 debug!("opaque_defn_ty = {:?}", opaque_defn_ty);
1284 let subst_opaque_defn_ty =
1285 opaque_defn_ty.concrete_type.subst(tcx, opaque_decl.substs);
1286 let renumbered_opaque_defn_ty =
1287 renumber::renumber_regions(infcx, &subst_opaque_defn_ty);
1235 1288
1236 debug!( 1289 debug!(
1237 "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?} \ 1290 "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
1238 concrete_is_opaque={}", 1291 opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
1239 opaque_decl.concrete_ty,
1240 infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty),
1241 opaque_defn_ty,
1242 concrete_is_opaque
1243 ); 1292 );
1244 1293
1245 // concrete_is_opaque is `true` when we're using an opaque `impl Trait`
1246 // type without 'revealing' it. For example, code like this:
1247 //
1248 // type Foo = impl Debug;
1249 // fn foo1() -> Foo { ... }
1250 // fn foo2() -> Foo { foo1() }
1251 //
1252 // In `foo2`, we're not revealing the type of `Foo` - we're
1253 // just treating it as the opaque type.
1254 //
1255 // When this occurs, we do *not* want to try to equate
1256 // the concrete type with the underlying defining type
1257 // of the opaque type - this will always fail, since
1258 // the defining type of an opaque type is always
1259 // some other type (e.g. not itself)
1260 // Essentially, none of the normal obligations apply here -
1261 // we're just passing around some unknown opaque type,
1262 // without actually looking at the underlying type it
1263 // gets 'revealed' into
1264
1265 if !concrete_is_opaque { 1294 if !concrete_is_opaque {
1295 // Equate concrete_ty (an inference variable) with
1296 // the renumbered type from typeck.
1266 obligations.add( 1297 obligations.add(
1267 infcx 1298 infcx
1268 .at(&ObligationCause::dummy(), param_env) 1299 .at(&ObligationCause::dummy(), param_env)
1269 .eq(opaque_decl.concrete_ty, opaque_defn_ty)?, 1300 .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
1301 );
1302 opaque_type_values.push((
1303 opaque_def_id,
1304 ty::ResolvedOpaqueTy {
1305 concrete_type: renumbered_opaque_defn_ty,
1306 substs: opaque_decl.substs,
1307 },
1308 ));
1309 } else {
1310 // We're using an opaque `impl Trait` type without
1311 // 'revealing' it. For example, code like this:
1312 //
1313 // type Foo = impl Debug;
1314 // fn foo1() -> Foo { ... }
1315 // fn foo2() -> Foo { foo1() }
1316 //
1317 // In `foo2`, we're not revealing the type of `Foo` - we're
1318 // just treating it as the opaque type.
1319 //
1320 // When this occurs, we do *not* want to try to equate
1321 // the concrete type with the underlying defining type
1322 // of the opaque type - this will always fail, since
1323 // the defining type of an opaque type is always
1324 // some other type (e.g. not itself)
1325 // Essentially, none of the normal obligations apply here -
1326 // we're just passing around some unknown opaque type,
1327 // without actually looking at the underlying type it
1328 // gets 'revealed' into
1329 debug!(
1330 "eq_opaque_type_and_type: non-defining use of {:?}",
1331 opaque_def_id,
1270 ); 1332 );
1271 } 1333 }
1272 } 1334 }
@@ -1282,6 +1344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1282 ), 1344 ),
1283 )?; 1345 )?;
1284 1346
1347 self.opaque_type_values.extend(opaque_type_values);
1348
1285 let universal_region_relations = self.universal_region_relations; 1349 let universal_region_relations = self.universal_region_relations;
1286 1350
1287 // Finally, if we instantiated the anon types successfully, we 1351 // Finally, if we instantiated the anon types successfully, we
@@ -1298,6 +1362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1298 infcx.constrain_opaque_type( 1362 infcx.constrain_opaque_type(
1299 opaque_def_id, 1363 opaque_def_id,
1300 &opaque_decl, 1364 &opaque_decl,
1365 GenerateMemberConstraints::IfNoStaticBound,
1301 universal_region_relations, 1366 universal_region_relations,
1302 ); 1367 );
1303 Ok(InferOk { value: (), obligations: vec![] }) 1368 Ok(InferOk { value: (), obligations: vec![] })
@@ -2512,7 +2577,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
2512 substs: SubstsRef<'tcx>, 2577 substs: SubstsRef<'tcx>,
2513 location: Location, 2578 location: Location,
2514 ) -> ty::InstantiatedPredicates<'tcx> { 2579 ) -> ty::InstantiatedPredicates<'tcx> {
2515 if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements { 2580 if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
2581 {
2516 let closure_constraints = QueryRegionConstraints { 2582 let closure_constraints = QueryRegionConstraints {
2517 outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs), 2583 outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs),
2518 2584
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6e80338..fab5501 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -178,6 +178,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
178 } 178 }
179 179
180 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { 180 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
181 // prevent
182 // * `&mut x.field`
183 // * `x.field = y;`
184 // * `&x.field` if `field`'s type has interior mutability
185 // because either of these would allow modifying the layout constrained field and
186 // insert values that violate the layout constraints.
187 if context.is_mutating_use() || context.is_borrow() {
188 self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
189 }
190
181 for (i, elem) in place.projection.iter().enumerate() { 191 for (i, elem) in place.projection.iter().enumerate() {
182 let proj_base = &place.projection[..i]; 192 let proj_base = &place.projection[..i];
183 193
@@ -198,24 +208,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
198 ); 208 );
199 } 209 }
200 } 210 }
201 let is_borrow_of_interior_mut = context.is_borrow()
202 && !Place::ty_from(place.local, proj_base, self.body, self.tcx).ty.is_freeze(
203 self.tcx,
204 self.param_env,
205 self.source_info.span,
206 );
207 // prevent
208 // * `&mut x.field`
209 // * `x.field = y;`
210 // * `&x.field` if `field`'s type has interior mutability
211 // because either of these would allow modifying the layout constrained field and
212 // insert values that violate the layout constraints.
213 if context.is_mutating_use() || is_borrow_of_interior_mut {
214 self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
215 }
216 let old_source_info = self.source_info; 211 let old_source_info = self.source_info;
217 if let (local, []) = (&place.local, proj_base) { 212 if let [] = proj_base {
218 let decl = &self.body.local_decls[*local]; 213 let decl = &self.body.local_decls[place.local];
219 if decl.internal { 214 if decl.internal {
220 if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { 215 if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
221 if self.tcx.is_mutable_static(def_id) { 216 if self.tcx.is_mutable_static(def_id) {
@@ -240,7 +235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
240 // Internal locals are used in the `move_val_init` desugaring. 235 // Internal locals are used in the `move_val_init` desugaring.
241 // We want to check unsafety against the source info of the 236 // We want to check unsafety against the source info of the
242 // desugaring, rather than the source info of the RHS. 237 // desugaring, rather than the source info of the RHS.
243 self.source_info = self.body.local_decls[*local].source_info; 238 self.source_info = self.body.local_decls[place.local].source_info;
244 } 239 }
245 } 240 }
246 } 241 }
@@ -396,6 +391,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
396 cursor = proj_base; 391 cursor = proj_base;
397 392
398 match elem { 393 match elem {
394 // Modifications behind a dereference don't affect the value of
395 // the pointer.
396 ProjectionElem::Deref => return,
399 ProjectionElem::Field(..) => { 397 ProjectionElem::Field(..) => {
400 let ty = 398 let ty =
401 Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty; 399 Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty;
@@ -409,7 +407,14 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
409 "mutating layout constrained fields cannot statically be \ 407 "mutating layout constrained fields cannot statically be \
410 checked for valid values", 408 checked for valid values",
411 ) 409 )
412 } else { 410
411 // Check `is_freeze` as late as possible to avoid cycle errors
412 // with opaque types.
413 } else if !place.ty(self.body, self.tcx).ty.is_freeze(
414 self.tcx,
415 self.param_env,
416 self.source_info.span,
417 ) {
413 ( 418 (
414 "borrow of layout constrained field with interior \ 419 "borrow of layout constrained field with interior \
415 mutability", 420 mutability",
@@ -417,6 +422,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
417 lose the constraints. Coupled with interior mutability, \ 422 lose the constraints. Coupled with interior mutability, \
418 the field can be changed to invalid values", 423 the field can be changed to invalid values",
419 ) 424 )
425 } else {
426 continue;
420 }; 427 };
421 self.require_unsafe( 428 self.require_unsafe(
422 description, 429 description,
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index 32b1f2b..5f8c0b0 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -670,14 +670,51 @@ fn construct_const<'a, 'tcx>(
670 builder.finish() 670 builder.finish()
671} 671}
672 672
673/// Construct MIR for a item that has had errors in type checking.
674///
675/// This is required because we may still want to run MIR passes on an item
676/// with type errors, but normal MIR construction can't handle that in general.
673fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> { 677fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
674 let owner_id = hir.tcx().hir().body_owner(body_id); 678 let tcx = hir.tcx();
675 let span = hir.tcx().hir().span(owner_id); 679 let owner_id = tcx.hir().body_owner(body_id);
676 let ty = hir.tcx().types.err; 680 let span = tcx.hir().span(owner_id);
677 let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None); 681 let ty = tcx.types.err;
682 let num_params = match hir.body_owner_kind {
683 hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(),
684 hir::BodyOwnerKind::Closure => {
685 if tcx.hir().body(body_id).generator_kind().is_some() {
686 // Generators have an implicit `self` parameter *and* a possibly
687 // implicit resume parameter.
688 2
689 } else {
690 // The implicit self parameter adds another local in MIR.
691 1 + tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len()
692 }
693 }
694 hir::BodyOwnerKind::Const => 0,
695 hir::BodyOwnerKind::Static(_) => 0,
696 };
697 let mut builder = Builder::new(hir, span, num_params, Safety::Safe, ty, span, None);
678 let source_info = builder.source_info(span); 698 let source_info = builder.source_info(span);
699 // Some MIR passes will expect the number of parameters to match the
700 // function declaration.
701 for _ in 0..num_params {
702 builder.local_decls.push(LocalDecl {
703 mutability: Mutability::Mut,
704 ty,
705 user_ty: UserTypeProjections::none(),
706 source_info,
707 internal: false,
708 local_info: LocalInfo::Other,
709 is_block_tail: None,
710 });
711 }
679 builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); 712 builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
680 builder.finish() 713 let mut body = builder.finish();
714 if tcx.hir().body(body_id).generator_kind.is_some() {
715 body.yield_ty = Some(ty);
716 }
717 body
681} 718}
682 719
683impl<'a, 'tcx> Builder<'a, 'tcx> { 720impl<'a, 'tcx> Builder<'a, 'tcx> {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index b4798fb..3a1622f 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -426,7 +426,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
426 fn visit_opaque_types(&mut self, span: Span) { 426 fn visit_opaque_types(&mut self, span: Span) {
427 for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { 427 for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
428 let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); 428 let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
429 let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); 429 let instantiated_ty =
430 self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id));
430 431
431 debug_assert!(!instantiated_ty.has_escaping_bound_vars()); 432 debug_assert!(!instantiated_ty.has_escaping_bound_vars());
432 433
@@ -444,7 +445,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
444 // figures out the concrete type with `U`, but the stored type is with `T`. 445 // figures out the concrete type with `U`, but the stored type is with `T`.
445 let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( 446 let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
446 def_id, 447 def_id,
447 opaque_defn, 448 opaque_defn.substs,
448 instantiated_ty, 449 instantiated_ty,
449 span, 450 span,
450 ); 451 );
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5349c32..1a505a3 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1,5 +1,3 @@
1// ignore-tidy-filelength
2
3//! "Collection" is the process of determining the type and other external 1//! "Collection" is the process of determining the type and other external
4//! details of each item in Rust. Collection is specifically concerned 2//! details of each item in Rust. Collection is specifically concerned
5//! with *inter-procedural* things -- for example, for a function 3//! with *inter-procedural* things -- for example, for a function
@@ -27,18 +25,16 @@ use rustc::hir::map::Map;
27use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; 25use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
28use rustc::mir::mono::Linkage; 26use rustc::mir::mono::Linkage;
29use rustc::session::parse::feature_err; 27use rustc::session::parse::feature_err;
30use rustc::traits;
31use rustc::ty::query::Providers; 28use rustc::ty::query::Providers;
32use rustc::ty::subst::GenericArgKind;
33use rustc::ty::subst::{InternalSubsts, Subst}; 29use rustc::ty::subst::{InternalSubsts, Subst};
34use rustc::ty::util::Discr; 30use rustc::ty::util::Discr;
35use rustc::ty::util::IntTypeExt; 31use rustc::ty::util::IntTypeExt;
36use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness}; 32use rustc::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
37use rustc::ty::{ReprOptions, ToPredicate}; 33use rustc::ty::{ReprOptions, ToPredicate, WithConstness};
38use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr}; 34use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
39use rustc_data_structures::captures::Captures; 35use rustc_data_structures::captures::Captures;
40use rustc_data_structures::fx::FxHashMap; 36use rustc_data_structures::fx::FxHashMap;
41use rustc_errors::{struct_span_err, Applicability, StashKey}; 37use rustc_errors::{struct_span_err, Applicability};
42use rustc_hir as hir; 38use rustc_hir as hir;
43use rustc_hir::def::{CtorKind, DefKind, Res}; 39use rustc_hir::def::{CtorKind, DefKind, Res};
44use rustc_hir::def_id::{DefId, LOCAL_CRATE}; 40use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -50,6 +46,8 @@ use rustc_target::spec::abi;
50use syntax::ast; 46use syntax::ast;
51use syntax::ast::{Ident, MetaItemKind}; 47use syntax::ast::{Ident, MetaItemKind};
52 48
49mod type_of;
50
53struct OnlySelfBounds(bool); 51struct OnlySelfBounds(bool);
54 52
55/////////////////////////////////////////////////////////////////////////// 53///////////////////////////////////////////////////////////////////////////
@@ -64,7 +62,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
64 62
65pub fn provide(providers: &mut Providers<'_>) { 63pub fn provide(providers: &mut Providers<'_>) {
66 *providers = Providers { 64 *providers = Providers {
67 type_of, 65 type_of: type_of::type_of,
68 generics_of, 66 generics_of,
69 predicates_of, 67 predicates_of,
70 predicates_defined_on, 68 predicates_defined_on,
@@ -1329,601 +1327,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
1329 }) 1327 })
1330} 1328}
1331 1329
1332fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
1333 struct_span_err!(
1334 tcx.sess,
1335 span,
1336 E0202,
1337 "associated types are not yet supported in inherent impls (see #8995)"
1338 )
1339 .emit();
1340}
1341
1342fn infer_placeholder_type(
1343 tcx: TyCtxt<'_>,
1344 def_id: DefId,
1345 body_id: hir::BodyId,
1346 span: Span,
1347 item_ident: Ident,
1348) -> Ty<'_> {
1349 let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id);
1350
1351 // If this came from a free `const` or `static mut?` item,
1352 // then the user may have written e.g. `const A = 42;`.
1353 // In this case, the parser has stashed a diagnostic for
1354 // us to improve in typeck so we do that now.
1355 match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
1356 Some(mut err) => {
1357 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
1358 // We are typeck and have the real type, so remove that and suggest the actual type.
1359 err.suggestions.clear();
1360 err.span_suggestion(
1361 span,
1362 "provide a type for the item",
1363 format!("{}: {}", item_ident, ty),
1364 Applicability::MachineApplicable,
1365 )
1366 .emit();
1367 }
1368 None => {
1369 let mut diag = bad_placeholder_type(tcx, vec![span]);
1370 if ty != tcx.types.err {
1371 diag.span_suggestion(
1372 span,
1373 "replace `_` with the correct type",
1374 ty.to_string(),
1375 Applicability::MaybeIncorrect,
1376 );
1377 }
1378 diag.emit();
1379 }
1380 }
1381
1382 ty
1383}
1384
1385fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1386 use rustc_hir::*;
1387
1388 let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
1389
1390 let icx = ItemCtxt::new(tcx, def_id);
1391
1392 match tcx.hir().get(hir_id) {
1393 Node::TraitItem(item) => match item.kind {
1394 TraitItemKind::Method(..) => {
1395 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1396 tcx.mk_fn_def(def_id, substs)
1397 }
1398 TraitItemKind::Const(ref ty, body_id) => body_id
1399 .and_then(|body_id| {
1400 if is_suggestable_infer_ty(ty) {
1401 Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
1402 } else {
1403 None
1404 }
1405 })
1406 .unwrap_or_else(|| icx.to_ty(ty)),
1407 TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
1408 TraitItemKind::Type(_, None) => {
1409 span_bug!(item.span, "associated type missing default");
1410 }
1411 },
1412
1413 Node::ImplItem(item) => match item.kind {
1414 ImplItemKind::Method(..) => {
1415 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1416 tcx.mk_fn_def(def_id, substs)
1417 }
1418 ImplItemKind::Const(ref ty, body_id) => {
1419 if is_suggestable_infer_ty(ty) {
1420 infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
1421 } else {
1422 icx.to_ty(ty)
1423 }
1424 }
1425 ImplItemKind::OpaqueTy(_) => {
1426 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
1427 report_assoc_ty_on_inherent_impl(tcx, item.span);
1428 }
1429
1430 find_opaque_ty_constraints(tcx, def_id)
1431 }
1432 ImplItemKind::TyAlias(ref ty) => {
1433 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
1434 report_assoc_ty_on_inherent_impl(tcx, item.span);
1435 }
1436
1437 icx.to_ty(ty)
1438 }
1439 },
1440
1441 Node::Item(item) => {
1442 match item.kind {
1443 ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
1444 if is_suggestable_infer_ty(ty) {
1445 infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
1446 } else {
1447 icx.to_ty(ty)
1448 }
1449 }
1450 ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
1451 icx.to_ty(self_ty)
1452 }
1453 ItemKind::Fn(..) => {
1454 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1455 tcx.mk_fn_def(def_id, substs)
1456 }
1457 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
1458 let def = tcx.adt_def(def_id);
1459 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1460 tcx.mk_adt(def, substs)
1461 }
1462 ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
1463 find_opaque_ty_constraints(tcx, def_id)
1464 }
1465 // Opaque types desugared from `impl Trait`.
1466 ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
1467 tcx.typeck_tables_of(owner)
1468 .concrete_opaque_types
1469 .get(&def_id)
1470 .map(|opaque| opaque.concrete_type)
1471 .unwrap_or_else(|| {
1472 // This can occur if some error in the
1473 // owner fn prevented us from populating
1474 // the `concrete_opaque_types` table.
1475 tcx.sess.delay_span_bug(
1476 DUMMY_SP,
1477 &format!(
1478 "owner {:?} has no opaque type for {:?} in its tables",
1479 owner, def_id,
1480 ),
1481 );
1482 tcx.types.err
1483 })
1484 }
1485 ItemKind::Trait(..)
1486 | ItemKind::TraitAlias(..)
1487 | ItemKind::Mod(..)
1488 | ItemKind::ForeignMod(..)
1489 | ItemKind::GlobalAsm(..)
1490 | ItemKind::ExternCrate(..)
1491 | ItemKind::Use(..) => {
1492 span_bug!(
1493 item.span,
1494 "compute_type_of_item: unexpected item type: {:?}",
1495 item.kind
1496 );
1497 }
1498 }
1499 }
1500
1501 Node::ForeignItem(foreign_item) => match foreign_item.kind {
1502 ForeignItemKind::Fn(..) => {
1503 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1504 tcx.mk_fn_def(def_id, substs)
1505 }
1506 ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
1507 ForeignItemKind::Type => tcx.mk_foreign(def_id),
1508 },
1509
1510 Node::Ctor(&ref def) | Node::Variant(hir::Variant { data: ref def, .. }) => match *def {
1511 VariantData::Unit(..) | VariantData::Struct(..) => {
1512 tcx.type_of(tcx.hir().get_parent_did(hir_id))
1513 }
1514 VariantData::Tuple(..) => {
1515 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1516 tcx.mk_fn_def(def_id, substs)
1517 }
1518 },
1519
1520 Node::Field(field) => icx.to_ty(&field.ty),
1521
1522 Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) => {
1523 if gen.is_some() {
1524 return tcx.typeck_tables_of(def_id).node_type(hir_id);
1525 }
1526
1527 let substs = InternalSubsts::identity_for_item(tcx, def_id);
1528 tcx.mk_closure(def_id, substs)
1529 }
1530
1531 Node::AnonConst(_) => {
1532 let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
1533 match parent_node {
1534 Node::Ty(&hir::Ty { kind: hir::TyKind::Array(_, ref constant), .. })
1535 | Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref constant), .. })
1536 | Node::Expr(&hir::Expr { kind: ExprKind::Repeat(_, ref constant), .. })
1537 if constant.hir_id == hir_id =>
1538 {
1539 tcx.types.usize
1540 }
1541
1542 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
1543 tcx.adt_def(tcx.hir().get_parent_did(hir_id)).repr.discr_type().to_ty(tcx)
1544 }
1545
1546 Node::Ty(&hir::Ty { kind: hir::TyKind::Path(_), .. })
1547 | Node::Expr(&hir::Expr { kind: ExprKind::Struct(..), .. })
1548 | Node::Expr(&hir::Expr { kind: ExprKind::Path(_), .. })
1549 | Node::TraitRef(..) => {
1550 let path = match parent_node {
1551 Node::Ty(&hir::Ty {
1552 kind: hir::TyKind::Path(QPath::Resolved(_, ref path)),
1553 ..
1554 })
1555 | Node::Expr(&hir::Expr {
1556 kind: ExprKind::Path(QPath::Resolved(_, ref path)),
1557 ..
1558 }) => Some(&**path),
1559 Node::Expr(&hir::Expr { kind: ExprKind::Struct(ref path, ..), .. }) => {
1560 if let QPath::Resolved(_, ref path) = **path {
1561 Some(&**path)
1562 } else {
1563 None
1564 }
1565 }
1566 Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(&**path),
1567 _ => None,
1568 };
1569
1570 if let Some(path) = path {
1571 let arg_index = path
1572 .segments
1573 .iter()
1574 .filter_map(|seg| seg.args.as_ref())
1575 .map(|generic_args| generic_args.args.as_ref())
1576 .find_map(|args| {
1577 args.iter()
1578 .filter(|arg| arg.is_const())
1579 .enumerate()
1580 .filter(|(_, arg)| arg.id() == hir_id)
1581 .map(|(index, _)| index)
1582 .next()
1583 })
1584 .unwrap_or_else(|| {
1585 bug!("no arg matching AnonConst in path");
1586 });
1587
1588 // We've encountered an `AnonConst` in some path, so we need to
1589 // figure out which generic parameter it corresponds to and return
1590 // the relevant type.
1591 let generics = match path.res {
1592 Res::Def(DefKind::Ctor(..), def_id) => {
1593 tcx.generics_of(tcx.parent(def_id).unwrap())
1594 }
1595 Res::Def(_, def_id) => tcx.generics_of(def_id),
1596 Res::Err => return tcx.types.err,
1597 res => {
1598 tcx.sess.delay_span_bug(
1599 DUMMY_SP,
1600 &format!("unexpected const parent path def {:?}", res,),
1601 );
1602 return tcx.types.err;
1603 }
1604 };
1605
1606 generics
1607 .params
1608 .iter()
1609 .filter(|param| {
1610 if let ty::GenericParamDefKind::Const = param.kind {
1611 true
1612 } else {
1613 false
1614 }
1615 })
1616 .nth(arg_index)
1617 .map(|param| tcx.type_of(param.def_id))
1618 // This is no generic parameter associated with the arg. This is
1619 // probably from an extra arg where one is not needed.
1620 .unwrap_or(tcx.types.err)
1621 } else {
1622 tcx.sess.delay_span_bug(
1623 DUMMY_SP,
1624 &format!("unexpected const parent path {:?}", parent_node,),
1625 );
1626 return tcx.types.err;
1627 }
1628 }
1629
1630 x => {
1631 tcx.sess.delay_span_bug(
1632 DUMMY_SP,
1633 &format!("unexpected const parent in type_of_def_id(): {:?}", x),
1634 );
1635 tcx.types.err
1636 }
1637 }
1638 }
1639
1640 Node::GenericParam(param) => match &param.kind {
1641 hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
1642 hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
1643 let ty = icx.to_ty(hir_ty);
1644 if !tcx.features().const_compare_raw_pointers {
1645 let err = match ty.peel_refs().kind {
1646 ty::FnPtr(_) => Some("function pointers"),
1647 ty::RawPtr(_) => Some("raw pointers"),
1648 _ => None,
1649 };
1650 if let Some(unsupported_type) = err {
1651 feature_err(
1652 &tcx.sess.parse_sess,
1653 sym::const_compare_raw_pointers,
1654 hir_ty.span,
1655 &format!(
1656 "using {} as const generic parameters is unstable",
1657 unsupported_type
1658 ),
1659 )
1660 .emit();
1661 };
1662 }
1663 if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
1664 .is_some()
1665 {
1666 struct_span_err!(
1667 tcx.sess,
1668 hir_ty.span,
1669 E0741,
1670 "the types of const generic parameters must derive `PartialEq` and `Eq`",
1671 )
1672 .span_label(
1673 hir_ty.span,
1674 format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
1675 )
1676 .emit();
1677 }
1678 ty
1679 }
1680 x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
1681 },
1682
1683 x => {
1684 bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
1685 }
1686 }
1687}
1688
1689fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1690 use rustc_hir::{ImplItem, Item, TraitItem};
1691
1692 debug!("find_opaque_ty_constraints({:?})", def_id);
1693
1694 struct ConstraintLocator<'tcx> {
1695 tcx: TyCtxt<'tcx>,
1696 def_id: DefId,
1697 // (first found type span, actual type, mapping from the opaque type's generic
1698 // parameters to the concrete type's generic parameters)
1699 //
1700 // The mapping is an index for each use site of a generic parameter in the concrete type
1701 //
1702 // The indices index into the generic parameters on the opaque type.
1703 found: Option<(Span, Ty<'tcx>, Vec<usize>)>,
1704 }
1705
1706 impl ConstraintLocator<'tcx> {
1707 fn check(&mut self, def_id: DefId) {
1708 // Don't try to check items that cannot possibly constrain the type.
1709 if !self.tcx.has_typeck_tables(def_id) {
1710 debug!(
1711 "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables",
1712 self.def_id, def_id,
1713 );
1714 return;
1715 }
1716 let ty = self.tcx.typeck_tables_of(def_id).concrete_opaque_types.get(&self.def_id);
1717 if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
1718 debug!(
1719 "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
1720 self.def_id, def_id, ty,
1721 );
1722
1723 // FIXME(oli-obk): trace the actual span from inference to improve errors.
1724 let span = self.tcx.def_span(def_id);
1725 // used to quickly look up the position of a generic parameter
1726 let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
1727 // Skipping binder is ok, since we only use this to find generic parameters and
1728 // their positions.
1729 for (idx, subst) in substs.iter().enumerate() {
1730 if let GenericArgKind::Type(ty) = subst.unpack() {
1731 if let ty::Param(p) = ty.kind {
1732 if index_map.insert(p, idx).is_some() {
1733 // There was already an entry for `p`, meaning a generic parameter
1734 // was used twice.
1735 self.tcx.sess.span_err(
1736 span,
1737 &format!(
1738 "defining opaque type use restricts opaque \
1739 type by using the generic parameter `{}` twice",
1740 p,
1741 ),
1742 );
1743 return;
1744 }
1745 } else {
1746 self.tcx.sess.delay_span_bug(
1747 span,
1748 &format!(
1749 "non-defining opaque ty use in defining scope: {:?}, {:?}",
1750 concrete_type, substs,
1751 ),
1752 );
1753 }
1754 }
1755 }
1756 // Compute the index within the opaque type for each generic parameter used in
1757 // the concrete type.
1758 let indices = concrete_type
1759 .subst(self.tcx, substs)
1760 .walk()
1761 .filter_map(|t| match &t.kind {
1762 ty::Param(p) => Some(*index_map.get(p).unwrap()),
1763 _ => None,
1764 })
1765 .collect();
1766 let is_param = |ty: Ty<'_>| match ty.kind {
1767 ty::Param(_) => true,
1768 _ => false,
1769 };
1770 let bad_substs: Vec<_> = substs
1771 .iter()
1772 .enumerate()
1773 .filter_map(|(i, k)| {
1774 if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
1775 })
1776 .filter(|(_, ty)| !is_param(ty))
1777 .collect();
1778
1779 if !bad_substs.is_empty() {
1780 let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
1781 for (i, bad_subst) in bad_substs {
1782 self.tcx.sess.span_err(
1783 span,
1784 &format!(
1785 "defining opaque type use does not fully define opaque type: \
1786 generic parameter `{}` is specified as concrete type `{}`",
1787 identity_substs.type_at(i),
1788 bad_subst
1789 ),
1790 );
1791 }
1792 } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
1793 let mut ty = concrete_type.walk().fuse();
1794 let mut p_ty = prev_ty.walk().fuse();
1795 let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
1796 // Type parameters are equal to any other type parameter for the purpose of
1797 // concrete type equality, as it is possible to obtain the same type just
1798 // by passing matching parameters to a function.
1799 (ty::Param(_), ty::Param(_)) => true,
1800 _ => t == p,
1801 });
1802 if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
1803 debug!("find_opaque_ty_constraints: span={:?}", span);
1804 // Found different concrete types for the opaque type.
1805 let mut err = self.tcx.sess.struct_span_err(
1806 span,
1807 "concrete type differs from previous defining opaque type use",
1808 );
1809 err.span_label(
1810 span,
1811 format!("expected `{}`, got `{}`", prev_ty, concrete_type),
1812 );
1813 err.span_note(prev_span, "previous use here");
1814 err.emit();
1815 } else if indices != *prev_indices {
1816 // Found "same" concrete types, but the generic parameter order differs.
1817 let mut err = self.tcx.sess.struct_span_err(
1818 span,
1819 "concrete type's generic parameters differ from previous defining use",
1820 );
1821 use std::fmt::Write;
1822 let mut s = String::new();
1823 write!(s, "expected [").unwrap();
1824 let list = |s: &mut String, indices: &Vec<usize>| {
1825 let mut indices = indices.iter().cloned();
1826 if let Some(first) = indices.next() {
1827 write!(s, "`{}`", substs[first]).unwrap();
1828 for i in indices {
1829 write!(s, ", `{}`", substs[i]).unwrap();
1830 }
1831 }
1832 };
1833 list(&mut s, prev_indices);
1834 write!(s, "], got [").unwrap();
1835 list(&mut s, &indices);
1836 write!(s, "]").unwrap();
1837 err.span_label(span, s);
1838 err.span_note(prev_span, "previous use here");
1839 err.emit();
1840 }
1841 } else {
1842 self.found = Some((span, concrete_type, indices));
1843 }
1844 } else {
1845 debug!(
1846 "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
1847 self.def_id, def_id,
1848 );
1849 }
1850 }
1851 }
1852
1853 impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
1854 type Map = Map<'tcx>;
1855
1856 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
1857 intravisit::NestedVisitorMap::All(&self.tcx.hir())
1858 }
1859 fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
1860 debug!("find_existential_constraints: visiting {:?}", it);
1861 let def_id = self.tcx.hir().local_def_id(it.hir_id);
1862 // The opaque type itself or its children are not within its reveal scope.
1863 if def_id != self.def_id {
1864 self.check(def_id);
1865 intravisit::walk_item(self, it);
1866 }
1867 }
1868 fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
1869 debug!("find_existential_constraints: visiting {:?}", it);
1870 let def_id = self.tcx.hir().local_def_id(it.hir_id);
1871 // The opaque type itself or its children are not within its reveal scope.
1872 if def_id != self.def_id {
1873 self.check(def_id);
1874 intravisit::walk_impl_item(self, it);
1875 }
1876 }
1877 fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
1878 debug!("find_existential_constraints: visiting {:?}", it);
1879 let def_id = self.tcx.hir().local_def_id(it.hir_id);
1880 self.check(def_id);
1881 intravisit::walk_trait_item(self, it);
1882 }
1883 }
1884
1885 let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
1886 let scope = tcx.hir().get_defining_scope(hir_id);
1887 let mut locator = ConstraintLocator { def_id, tcx, found: None };
1888
1889 debug!("find_opaque_ty_constraints: scope={:?}", scope);
1890
1891 if scope == hir::CRATE_HIR_ID {
1892 intravisit::walk_crate(&mut locator, tcx.hir().krate());
1893 } else {
1894 debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
1895 match tcx.hir().get(scope) {
1896 // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
1897 // This allows our visitor to process the defining item itself, causing
1898 // it to pick up any 'sibling' defining uses.
1899 //
1900 // For example, this code:
1901 // ```
1902 // fn foo() {
1903 // type Blah = impl Debug;
1904 // let my_closure = || -> Blah { true };
1905 // }
1906 // ```
1907 //
1908 // requires us to explicitly process `foo()` in order
1909 // to notice the defining usage of `Blah`.
1910 Node::Item(ref it) => locator.visit_item(it),
1911 Node::ImplItem(ref it) => locator.visit_impl_item(it),
1912 Node::TraitItem(ref it) => locator.visit_trait_item(it),
1913 other => bug!("{:?} is not a valid scope for an opaque type item", other),
1914 }
1915 }
1916
1917 match locator.found {
1918 Some((_, ty, _)) => ty,
1919 None => {
1920 let span = tcx.def_span(def_id);
1921 tcx.sess.span_err(span, "could not find defining uses");
1922 tcx.types.err
1923 }
1924 }
1925}
1926
1927fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { 1330fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
1928 generic_args 1331 generic_args
1929 .iter() 1332 .iter()
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
new file mode 100644
index 0000000..8b6dba7
--- /dev/null
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -0,0 +1,661 @@
1use rustc::hir::map::Map;
2use rustc::session::parse::feature_err;
3use rustc::traits;
4use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst};
5use rustc::ty::util::IntTypeExt;
6use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
7use rustc_data_structures::fx::FxHashMap;
8use rustc_errors::{struct_span_err, Applicability, StashKey};
9use rustc_hir as hir;
10use rustc_hir::def::{DefKind, Res};
11use rustc_hir::def_id::DefId;
12use rustc_hir::intravisit;
13use rustc_hir::intravisit::Visitor;
14use rustc_hir::Node;
15use rustc_span::symbol::{sym, Ident};
16use rustc_span::{Span, DUMMY_SP};
17
18use super::ItemCtxt;
19use super::{bad_placeholder_type, is_suggestable_infer_ty};
20
21pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
22 use rustc_hir::*;
23
24 let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
25
26 let icx = ItemCtxt::new(tcx, def_id);
27
28 match tcx.hir().get(hir_id) {
29 Node::TraitItem(item) => match item.kind {
30 TraitItemKind::Method(..) => {
31 let substs = InternalSubsts::identity_for_item(tcx, def_id);
32 tcx.mk_fn_def(def_id, substs)
33 }
34 TraitItemKind::Const(ref ty, body_id) => body_id
35 .and_then(|body_id| {
36 if is_suggestable_infer_ty(ty) {
37 Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
38 } else {
39 None
40 }
41 })
42 .unwrap_or_else(|| icx.to_ty(ty)),
43 TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
44 TraitItemKind::Type(_, None) => {
45 span_bug!(item.span, "associated type missing default");
46 }
47 },
48
49 Node::ImplItem(item) => match item.kind {
50 ImplItemKind::Method(..) => {
51 let substs = InternalSubsts::identity_for_item(tcx, def_id);
52 tcx.mk_fn_def(def_id, substs)
53 }
54 ImplItemKind::Const(ref ty, body_id) => {
55 if is_suggestable_infer_ty(ty) {
56 infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
57 } else {
58 icx.to_ty(ty)
59 }
60 }
61 ImplItemKind::OpaqueTy(_) => {
62 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
63 report_assoc_ty_on_inherent_impl(tcx, item.span);
64 }
65
66 find_opaque_ty_constraints(tcx, def_id)
67 }
68 ImplItemKind::TyAlias(ref ty) => {
69 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
70 report_assoc_ty_on_inherent_impl(tcx, item.span);
71 }
72
73 icx.to_ty(ty)
74 }
75 },
76
77 Node::Item(item) => {
78 match item.kind {
79 ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
80 if is_suggestable_infer_ty(ty) {
81 infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
82 } else {
83 icx.to_ty(ty)
84 }
85 }
86 ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
87 icx.to_ty(self_ty)
88 }
89 ItemKind::Fn(..) => {
90 let substs = InternalSubsts::identity_for_item(tcx, def_id);
91 tcx.mk_fn_def(def_id, substs)
92 }
93 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
94 let def = tcx.adt_def(def_id);
95 let substs = InternalSubsts::identity_for_item(tcx, def_id);
96 tcx.mk_adt(def, substs)
97 }
98 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
99 find_opaque_ty_constraints(tcx, def_id)
100 }
101 // Opaque types desugared from `impl Trait`.
102 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => {
103 let concrete_types = match origin {
104 OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => {
105 &tcx.mir_borrowck(owner).concrete_opaque_types
106 }
107 OpaqueTyOrigin::Misc => {
108 // We shouldn't leak borrowck results through impl trait in bindings.
109 // For example, we shouldn't be able to tell if `x` in
110 // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`.
111 &tcx.typeck_tables_of(owner).concrete_opaque_types
112 }
113 OpaqueTyOrigin::TypeAlias => {
114 span_bug!(item.span, "Type alias impl trait shouldn't have an owner")
115 }
116 };
117 let concrete_ty = concrete_types
118 .get(&def_id)
119 .map(|opaque| opaque.concrete_type)
120 .unwrap_or_else(|| {
121 tcx.sess.delay_span_bug(
122 DUMMY_SP,
123 &format!(
124 "owner {:?} has no opaque type for {:?} in its tables",
125 owner, def_id,
126 ),
127 );
128 if tcx.typeck_tables_of(owner).tainted_by_errors {
129 // Some error in the
130 // owner fn prevented us from populating
131 // the `concrete_opaque_types` table.
132 tcx.types.err
133 } else {
134 // We failed to resolve the opaque type or it
135 // resolves to itself. Return the non-revealed
136 // type, which should result in E0720.
137 tcx.mk_opaque(
138 def_id,
139 InternalSubsts::identity_for_item(tcx, def_id),
140 )
141 }
142 });
143 debug!("concrete_ty = {:?}", concrete_ty);
144 if concrete_ty.has_erased_regions() {
145 // FIXME(impl_trait_in_bindings) Handle this case.
146 tcx.sess.span_fatal(
147 item.span,
148 "lifetimes in impl Trait types in bindings are not currently supported",
149 );
150 }
151 concrete_ty
152 }
153 ItemKind::Trait(..)
154 | ItemKind::TraitAlias(..)
155 | ItemKind::Mod(..)
156 | ItemKind::ForeignMod(..)
157 | ItemKind::GlobalAsm(..)
158 | ItemKind::ExternCrate(..)
159 | ItemKind::Use(..) => {
160 span_bug!(
161 item.span,
162 "compute_type_of_item: unexpected item type: {:?}",
163 item.kind
164 );
165 }
166 }
167 }
168
169 Node::ForeignItem(foreign_item) => match foreign_item.kind {
170 ForeignItemKind::Fn(..) => {
171 let substs = InternalSubsts::identity_for_item(tcx, def_id);
172 tcx.mk_fn_def(def_id, substs)
173 }
174 ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
175 ForeignItemKind::Type => tcx.mk_foreign(def_id),
176 },
177
178 Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
179 VariantData::Unit(..) | VariantData::Struct(..) => {
180 tcx.type_of(tcx.hir().get_parent_did(hir_id))
181 }
182 VariantData::Tuple(..) => {
183 let substs = InternalSubsts::identity_for_item(tcx, def_id);
184 tcx.mk_fn_def(def_id, substs)
185 }
186 },
187
188 Node::Field(field) => icx.to_ty(&field.ty),
189
190 Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => {
191 if gen.is_some() {
192 return tcx.typeck_tables_of(def_id).node_type(hir_id);
193 }
194
195 let substs = InternalSubsts::identity_for_item(tcx, def_id);
196 tcx.mk_closure(def_id, substs)
197 }
198
199 Node::AnonConst(_) => {
200 let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
201 match parent_node {
202 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
203 | Node::Ty(&Ty { kind: TyKind::Typeof(ref constant), .. })
204 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
205 if constant.hir_id == hir_id =>
206 {
207 tcx.types.usize
208 }
209
210 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
211 tcx.adt_def(tcx.hir().get_parent_did(hir_id)).repr.discr_type().to_ty(tcx)
212 }
213
214 Node::Ty(&Ty { kind: TyKind::Path(_), .. })
215 | Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
216 | Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
217 | Node::TraitRef(..) => {
218 let path = match parent_node {
219 Node::Ty(&Ty {
220 kind: TyKind::Path(QPath::Resolved(_, ref path)), ..
221 })
222 | Node::Expr(&Expr {
223 kind: ExprKind::Path(QPath::Resolved(_, ref path)),
224 ..
225 }) => Some(&**path),
226 Node::Expr(&Expr { kind: ExprKind::Struct(ref path, ..), .. }) => {
227 if let QPath::Resolved(_, ref path) = **path {
228 Some(&**path)
229 } else {
230 None
231 }
232 }
233 Node::TraitRef(&TraitRef { ref path, .. }) => Some(&**path),
234 _ => None,
235 };
236
237 if let Some(path) = path {
238 let arg_index = path
239 .segments
240 .iter()
241 .filter_map(|seg| seg.args.as_ref())
242 .map(|generic_args| generic_args.args.as_ref())
243 .find_map(|args| {
244 args.iter()
245 .filter(|arg| arg.is_const())
246 .enumerate()
247 .filter(|(_, arg)| arg.id() == hir_id)
248 .map(|(index, _)| index)
249 .next()
250 })
251 .unwrap_or_else(|| {
252 bug!("no arg matching AnonConst in path");
253 });
254
255 // We've encountered an `AnonConst` in some path, so we need to
256 // figure out which generic parameter it corresponds to and return
257 // the relevant type.
258 let generics = match path.res {
259 Res::Def(DefKind::Ctor(..), def_id) => {
260 tcx.generics_of(tcx.parent(def_id).unwrap())
261 }
262 Res::Def(_, def_id) => tcx.generics_of(def_id),
263 Res::Err => return tcx.types.err,
264 res => {
265 tcx.sess.delay_span_bug(
266 DUMMY_SP,
267 &format!("unexpected const parent path def {:?}", res,),
268 );
269 return tcx.types.err;
270 }
271 };
272
273 generics
274 .params
275 .iter()
276 .filter(|param| {
277 if let ty::GenericParamDefKind::Const = param.kind {
278 true
279 } else {
280 false
281 }
282 })
283 .nth(arg_index)
284 .map(|param| tcx.type_of(param.def_id))
285 // This is no generic parameter associated with the arg. This is
286 // probably from an extra arg where one is not needed.
287 .unwrap_or(tcx.types.err)
288 } else {
289 tcx.sess.delay_span_bug(
290 DUMMY_SP,
291 &format!("unexpected const parent path {:?}", parent_node,),
292 );
293 return tcx.types.err;
294 }
295 }
296
297 x => {
298 tcx.sess.delay_span_bug(
299 DUMMY_SP,
300 &format!("unexpected const parent in type_of_def_id(): {:?}", x),
301 );
302 tcx.types.err
303 }
304 }
305 }
306
307 Node::GenericParam(param) => match &param.kind {
308 GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
309 GenericParamKind::Const { ty: ref hir_ty, .. } => {
310 let ty = icx.to_ty(hir_ty);
311 if !tcx.features().const_compare_raw_pointers {
312 let err = match ty.peel_refs().kind {
313 ty::FnPtr(_) => Some("function pointers"),
314 ty::RawPtr(_) => Some("raw pointers"),
315 _ => None,
316 };
317 if let Some(unsupported_type) = err {
318 feature_err(
319 &tcx.sess.parse_sess,
320 sym::const_compare_raw_pointers,
321 hir_ty.span,
322 &format!(
323 "using {} as const generic parameters is unstable",
324 unsupported_type
325 ),
326 )
327 .emit();
328 };
329 }
330 if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
331 .is_some()
332 {
333 struct_span_err!(
334 tcx.sess,
335 hir_ty.span,
336 E0741,
337 "the types of const generic parameters must derive `PartialEq` and `Eq`",
338 )
339 .span_label(
340 hir_ty.span,
341 format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
342 )
343 .emit();
344 }
345 ty
346 }
347 x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
348 },
349
350 x => {
351 bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
352 }
353 }
354}
355
356fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
357 use rustc_hir::{Expr, ImplItem, Item, TraitItem};
358
359 debug!("find_opaque_ty_constraints({:?})", def_id);
360
361 struct ConstraintLocator<'tcx> {
362 tcx: TyCtxt<'tcx>,
363 def_id: DefId,
364 // (first found type span, actual type, mapping from the opaque type's generic
365 // parameters to the concrete type's generic parameters)
366 //
367 // The mapping is an index for each use site of a generic parameter in the concrete type
368 //
369 // The indices index into the generic parameters on the opaque type.
370 found: Option<(Span, Ty<'tcx>, Vec<usize>)>,
371 }
372
373 impl ConstraintLocator<'_> {
374 fn check(&mut self, def_id: DefId) {
375 // Don't try to check items that cannot possibly constrain the type.
376 if !self.tcx.has_typeck_tables(def_id) {
377 debug!(
378 "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables",
379 self.def_id, def_id,
380 );
381 return;
382 }
383 // Calling `mir_borrowck` can lead to cycle errors through
384 // const-checking, avoid calling it if we don't have to.
385 if !self.tcx.typeck_tables_of(def_id).concrete_opaque_types.contains_key(&self.def_id) {
386 debug!(
387 "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
388 self.def_id, def_id,
389 );
390 return;
391 }
392 // Use borrowck to get the type with unerased regions.
393 let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id);
394 if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
395 debug!(
396 "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
397 self.def_id, def_id, ty,
398 );
399
400 // FIXME(oli-obk): trace the actual span from inference to improve errors.
401 let span = self.tcx.def_span(def_id);
402 // used to quickly look up the position of a generic parameter
403 let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
404 // Skipping binder is ok, since we only use this to find generic parameters and
405 // their positions.
406 for (idx, subst) in substs.iter().enumerate() {
407 if let GenericArgKind::Type(ty) = subst.unpack() {
408 if let ty::Param(p) = ty.kind {
409 if index_map.insert(p, idx).is_some() {
410 // There was already an entry for `p`, meaning a generic parameter
411 // was used twice.
412 self.tcx.sess.span_err(
413 span,
414 &format!(
415 "defining opaque type use restricts opaque \
416 type by using the generic parameter `{}` twice",
417 p,
418 ),
419 );
420 return;
421 }
422 } else {
423 self.tcx.sess.delay_span_bug(
424 span,
425 &format!(
426 "non-defining opaque ty use in defining scope: {:?}, {:?}",
427 concrete_type, substs,
428 ),
429 );
430 }
431 }
432 }
433 // Compute the index within the opaque type for each generic parameter used in
434 // the concrete type.
435 let indices = concrete_type
436 .subst(self.tcx, substs)
437 .walk()
438 .filter_map(|t| match &t.kind {
439 ty::Param(p) => Some(*index_map.get(p).unwrap()),
440 _ => None,
441 })
442 .collect();
443 let is_param = |ty: Ty<'_>| match ty.kind {
444 ty::Param(_) => true,
445 _ => false,
446 };
447 let bad_substs: Vec<_> = substs
448 .iter()
449 .enumerate()
450 .filter_map(|(i, k)| {
451 if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
452 })
453 .filter(|(_, ty)| !is_param(ty))
454 .collect();
455 if !bad_substs.is_empty() {
456 let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
457 for (i, bad_subst) in bad_substs {
458 self.tcx.sess.span_err(
459 span,
460 &format!(
461 "defining opaque type use does not fully define opaque type: \
462 generic parameter `{}` is specified as concrete type `{}`",
463 identity_substs.type_at(i),
464 bad_subst
465 ),
466 );
467 }
468 } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
469 let mut ty = concrete_type.walk().fuse();
470 let mut p_ty = prev_ty.walk().fuse();
471 let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
472 // Type parameters are equal to any other type parameter for the purpose of
473 // concrete type equality, as it is possible to obtain the same type just
474 // by passing matching parameters to a function.
475 (ty::Param(_), ty::Param(_)) => true,
476 _ => t == p,
477 });
478 if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
479 debug!("find_opaque_ty_constraints: span={:?}", span);
480 // Found different concrete types for the opaque type.
481 let mut err = self.tcx.sess.struct_span_err(
482 span,
483 "concrete type differs from previous defining opaque type use",
484 );
485 err.span_label(
486 span,
487 format!("expected `{}`, got `{}`", prev_ty, concrete_type),
488 );
489 err.span_note(prev_span, "previous use here");
490 err.emit();
491 } else if indices != *prev_indices {
492 // Found "same" concrete types, but the generic parameter order differs.
493 let mut err = self.tcx.sess.struct_span_err(
494 span,
495 "concrete type's generic parameters differ from previous defining use",
496 );
497 use std::fmt::Write;
498 let mut s = String::new();
499 write!(s, "expected [").unwrap();
500 let list = |s: &mut String, indices: &Vec<usize>| {
501 let mut indices = indices.iter().cloned();
502 if let Some(first) = indices.next() {
503 write!(s, "`{}`", substs[first]).unwrap();
504 for i in indices {
505 write!(s, ", `{}`", substs[i]).unwrap();
506 }
507 }
508 };
509 list(&mut s, prev_indices);
510 write!(s, "], got [").unwrap();
511 list(&mut s, &indices);
512 write!(s, "]").unwrap();
513 err.span_label(span, s);
514 err.span_note(prev_span, "previous use here");
515 err.emit();
516 }
517 } else {
518 self.found = Some((span, concrete_type, indices));
519 }
520 } else {
521 debug!(
522 "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
523 self.def_id, def_id,
524 );
525 }
526 }
527 }
528
529 impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
530 type Map = Map<'tcx>;
531
532 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
533 intravisit::NestedVisitorMap::All(&self.tcx.hir())
534 }
535 fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
536 if let hir::ExprKind::Closure(..) = ex.kind {
537 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
538 self.check(def_id);
539 }
540 intravisit::walk_expr(self, ex);
541 }
542 fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
543 debug!("find_existential_constraints: visiting {:?}", it);
544 let def_id = self.tcx.hir().local_def_id(it.hir_id);
545 // The opaque type itself or its children are not within its reveal scope.
546 if def_id != self.def_id {
547 self.check(def_id);
548 intravisit::walk_item(self, it);
549 }
550 }
551 fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
552 debug!("find_existential_constraints: visiting {:?}", it);
553 let def_id = self.tcx.hir().local_def_id(it.hir_id);
554 // The opaque type itself or its children are not within its reveal scope.
555 if def_id != self.def_id {
556 self.check(def_id);
557 intravisit::walk_impl_item(self, it);
558 }
559 }
560 fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
561 debug!("find_existential_constraints: visiting {:?}", it);
562 let def_id = self.tcx.hir().local_def_id(it.hir_id);
563 self.check(def_id);
564 intravisit::walk_trait_item(self, it);
565 }
566 }
567
568 let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
569 let scope = tcx.hir().get_defining_scope(hir_id);
570 let mut locator = ConstraintLocator { def_id, tcx, found: None };
571
572 debug!("find_opaque_ty_constraints: scope={:?}", scope);
573
574 if scope == hir::CRATE_HIR_ID {
575 intravisit::walk_crate(&mut locator, tcx.hir().krate());
576 } else {
577 debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
578 match tcx.hir().get(scope) {
579 // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
580 // This allows our visitor to process the defining item itself, causing
581 // it to pick up any 'sibling' defining uses.
582 //
583 // For example, this code:
584 // ```
585 // fn foo() {
586 // type Blah = impl Debug;
587 // let my_closure = || -> Blah { true };
588 // }
589 // ```
590 //
591 // requires us to explicitly process `foo()` in order
592 // to notice the defining usage of `Blah`.
593 Node::Item(ref it) => locator.visit_item(it),
594 Node::ImplItem(ref it) => locator.visit_impl_item(it),
595 Node::TraitItem(ref it) => locator.visit_trait_item(it),
596 other => bug!("{:?} is not a valid scope for an opaque type item", other),
597 }
598 }
599
600 match locator.found {
601 Some((_, ty, _)) => ty,
602 None => {
603 let span = tcx.def_span(def_id);
604 tcx.sess.span_err(span, "could not find defining uses");
605 tcx.types.err
606 }
607 }
608}
609
610fn infer_placeholder_type(
611 tcx: TyCtxt<'_>,
612 def_id: DefId,
613 body_id: hir::BodyId,
614 span: Span,
615 item_ident: Ident,
616) -> Ty<'_> {
617 let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id);
618
619 // If this came from a free `const` or `static mut?` item,
620 // then the user may have written e.g. `const A = 42;`.
621 // In this case, the parser has stashed a diagnostic for
622 // us to improve in typeck so we do that now.
623 match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
624 Some(mut err) => {
625 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
626 // We are typeck and have the real type, so remove that and suggest the actual type.
627 err.suggestions.clear();
628 err.span_suggestion(
629 span,
630 "provide a type for the item",
631 format!("{}: {}", item_ident, ty),
632 Applicability::MachineApplicable,
633 )
634 .emit();
635 }
636 None => {
637 let mut diag = bad_placeholder_type(tcx, vec![span]);
638 if ty != tcx.types.err {
639 diag.span_suggestion(
640 span,
641 "replace `_` with the correct type",
642 ty.to_string(),
643 Applicability::MaybeIncorrect,
644 );
645 }
646 diag.emit();
647 }
648 }
649
650 ty
651}
652
653fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
654 struct_span_err!(
655 tcx.sess,
656 span,
657 E0202,
658 "associated types are not yet supported in inherent impls (see #8995)"
659 )
660 .emit();
661}
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index e9c18b5..0a765a1 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -120,11 +120,26 @@ fn enforce_impl_params_are_constrained(
120 let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs 120 let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs
121 .iter() 121 .iter()
122 .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id)) 122 .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id))
123 .filter(|&def_id| { 123 .flat_map(|def_id| {
124 let item = tcx.associated_item(def_id); 124 let item = tcx.associated_item(def_id);
125 item.kind == ty::AssocKind::Type && item.defaultness.has_value() 125 match item.kind {
126 ty::AssocKind::Type => {
127 if item.defaultness.has_value() {
128 cgp::parameters_for(&tcx.type_of(def_id), true)
129 } else {
130 Vec::new()
131 }
132 }
133 ty::AssocKind::OpaqueTy => {
134 // We don't know which lifetimes appear in the actual
135 // opaque type, so use all of the lifetimes that appear
136 // in the type's predicates.
137 let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
138 cgp::parameters_for(&predicates, true)
139 }
140 ty::AssocKind::Method | ty::AssocKind::Const => Vec::new(),
141 }
126 }) 142 })
127 .flat_map(|def_id| cgp::parameters_for(&tcx.type_of(def_id), true))
128 .collect(); 143 .collect();
129 144
130 for param in &impl_generics.params { 145 for param in &impl_generics.params {
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index f74c84e..7b1beb1 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -16,9 +16,10 @@ pub use core::future::*;
16/// 16///
17/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give 17/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
18/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). 18/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
19// This is `const` to avoid extra errors after we recover from `const async fn`
19#[doc(hidden)] 20#[doc(hidden)]
20#[unstable(feature = "gen_future", issue = "50547")] 21#[unstable(feature = "gen_future", issue = "50547")]
21pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> { 22pub const fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
22 GenFuture(x) 23 GenFuture(x)
23} 24}
24 25
diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
index 4ae3971..8e0e1ce 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
@@ -1,11 +1,3 @@
1error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
2 --> $DIR/issue-63388-1.rs:12:10
3 |
4LL | ) -> &dyn Foo
5 | ^^^^^^^^
6 |
7 = note: hidden type `impl std::future::Future` captures lifetime '_#22r
8
9error: lifetime may not live long enough 1error: lifetime may not live long enough
10 --> $DIR/issue-63388-1.rs:13:5 2 --> $DIR/issue-63388-1.rs:13:5
11 | 3 |
@@ -19,6 +11,5 @@ LL | | foo
19LL | | } 11LL | | }
20 | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` 12 | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
21 13
22error: aborting due to 2 previous errors 14error: aborting due to previous error
23 15
24For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs
index b3c5973..57a9f17 100644
--- a/src/test/ui/async-await/no-const-async.rs
+++ b/src/test/ui/async-await/no-const-async.rs
@@ -3,3 +3,4 @@
3 3
4pub const async fn x() {} 4pub const async fn x() {}
5//~^ ERROR functions cannot be both `const` and `async` 5//~^ ERROR functions cannot be both `const` and `async`
6//~| ERROR `impl Trait` in const fn is unstable
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index f6ae0f1..07559cd 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -7,5 +7,15 @@ LL | pub const async fn x() {}
7 | | `async` because of this 7 | | `async` because of this
8 | `const` because of this 8 | `const` because of this
9 9
10error: aborting due to previous error 10error[E0723]: `impl Trait` in const fn is unstable
11 --> $DIR/no-const-async.rs:4:24
12 |
13LL | pub const async fn x() {}
14 | ^
15 |
16 = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
17 = help: add `#![feature(const_fn)]` to the crate attributes to enable
18
19error: aborting due to 2 previous errors
11 20
21For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs
new file mode 100644
index 0000000..57198cb
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs
@@ -0,0 +1,14 @@
1#![feature(unboxed_closures)]
2
3// Tests that we can't assign to or mutably borrow upvars from `Fn`
4// closures (issue #17780)
5
6fn main() {}
7
8fn bar() -> impl Fn() -> usize {
9 let mut x = 0;
10 move || {
11 x += 1; //~ ERROR cannot assign
12 x
13 }
14}
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr
new file mode 100644
index 0000000..003c40d
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr
@@ -0,0 +1,16 @@
1error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
2 --> $DIR/borrow-immutable-upvar-mutation-impl-trait.rs:11:9
3 |
4LL | fn bar() -> impl Fn() -> usize {
5 | --- ------------------ change this to return `FnMut` instead of `Fn`
6LL | let mut x = 0;
7LL | / move || {
8LL | | x += 1;
9 | | ^^^^^^ cannot assign
10LL | | x
11LL | | }
12 | |_____- in this closure
13
14error: aborting due to previous error
15
16For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
index 62e27bc..e2f0166 100644
--- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
@@ -3,10 +3,16 @@
3// Tests that we can't assign to or mutably borrow upvars from `Fn` 3// Tests that we can't assign to or mutably borrow upvars from `Fn`
4// closures (issue #17780) 4// closures (issue #17780)
5 5
6fn set(x: &mut usize) { *x = 5; } 6fn set(x: &mut usize) {
7 *x = 5;
8}
7 9
8fn to_fn<A,F:Fn<A>>(f: F) -> F { f } 10fn to_fn<A, F: Fn<A>>(f: F) -> F {
9fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f } 11 f
12}
13fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F {
14 f
15}
10 16
11fn main() { 17fn main() {
12 // By-ref captures 18 // By-ref captures
@@ -33,7 +39,11 @@ fn main() {
33 let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow 39 let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow
34 40
35 let mut z = 0; 41 let mut z = 0;
36 let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign 42 let _h = to_fn_mut(move || {