/// The MIR represents some form of constant. The signature then
/// is that it has no inputs and a single return value, which is
/// the value of the constant.
- Const(Ty<'tcx>),
+ Const(DefId, &'tcx Substs<'tcx>),
}
#[derive(Debug)]
/// see `DefiningTy` for details.
fn defining_ty(&self) -> DefiningTy<'tcx> {
let tcx = self.infcx.tcx;
-
let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
- let defining_ty = if self.mir_def_id == closure_base_def_id {
- tcx.type_of(closure_base_def_id)
- } else {
- let tables = tcx.typeck_tables_of(self.mir_def_id);
- tables.node_id_to_type(self.mir_hir_id)
- };
-
- let defining_ty = self.infcx
- .replace_free_regions_with_nll_infer_vars(FR, &defining_ty);
-
match tcx.hir.body_owner_kind(self.mir_node_id) {
- BodyOwnerKind::Fn => match defining_ty.sty {
- ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs),
- ty::TyGenerator(def_id, substs, interior) => {
- DefiningTy::Generator(def_id, substs, interior)
+ BodyOwnerKind::Fn => {
+ let defining_ty = if self.mir_def_id == closure_base_def_id {
+ tcx.type_of(closure_base_def_id)
+ } else {
+ let tables = tcx.typeck_tables_of(self.mir_def_id);
+ tables.node_id_to_type(self.mir_hir_id)
+ };
+
+ let defining_ty = self.infcx
+ .replace_free_regions_with_nll_infer_vars(FR, &defining_ty);
+
+ match defining_ty.sty {
+ ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs),
+ ty::TyGenerator(def_id, substs, interior) => {
+ DefiningTy::Generator(def_id, substs, interior)
+ }
+ ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
+ _ => span_bug!(
+ tcx.def_span(self.mir_def_id),
+ "expected defining type for `{:?}`: `{:?}`",
+ self.mir_def_id,
+ defining_ty
+ ),
}
- ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
- _ => span_bug!(
- tcx.def_span(self.mir_def_id),
- "expected defining type for `{:?}`: `{:?}`",
- self.mir_def_id,
- defining_ty
- ),
- },
- BodyOwnerKind::Const | BodyOwnerKind::Static(..) => DefiningTy::Const(defining_ty),
+ }
+
+ BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
+ assert_eq!(closure_base_def_id, self.mir_def_id);
+ let identity_substs = Substs::identity_for_item(tcx, closure_base_def_id);
+ let substs = self.infcx
+ .replace_free_regions_with_nll_infer_vars(FR, &identity_substs);
+ DefiningTy::Const(self.mir_def_id, substs)
+ }
}
}
substs.substs
}
- DefiningTy::FnDef(_, substs) => substs,
-
- // When we encounter a constant body, just return whatever
- // substitutions are in scope for that constant.
- DefiningTy::Const(_) => {
- identity_substs
- }
+ DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs,
};
let global_mapping = iter::once((gcx.types.re_static, fr_static));
sig.inputs_and_output()
}
- // For a constant body, there are no inputs, and one
- // "output" (the type of the constant).
- DefiningTy::Const(ty) => ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))),
+ DefiningTy::Const(def_id, _) => {
+ // For a constant body, there are no inputs, and one
+ // "output" (the type of the constant).
+ assert_eq!(self.mir_def_id, def_id);
+ let ty = tcx.type_of(def_id);
+ let ty = indices.fold_to_region_vids(tcx, &ty);
+ ty::Binder::dummy(tcx.mk_type_list(iter::once(ty)))
+ }
}
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test cases where we put various lifetime constraints on trait
+// associated constants.
+
+#![feature(rustc_attrs)]
+
+use std::option::Option;
+
+trait Anything<'a: 'b, 'b> {
+ const AC: Option<&'b str>;
+}
+
+struct OKStruct { }
+
+impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct {
+ const AC: Option<&'b str> = None;
+}
+
+struct FailStruct1 { }
+
+impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+ const AC: Option<&'c str> = None;
+ //~^ ERROR: mismatched types
+}
+
+struct FailStruct2 { }
+
+impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
+ const AC: Option<&'a str> = None;
+ //~^ ERROR: mismatched types
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/trait-associated-constant.rs:31:5
+ |
+31 | const AC: Option<&'c str> = None;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected type `std::option::Option<&'b str>`
+ found type `std::option::Option<&'c str>`
+note: the lifetime 'c as defined on the impl at 30:1...
+ --> $DIR/trait-associated-constant.rs:30:1
+ |
+30 | / impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+31 | | const AC: Option<&'c str> = None;
+32 | | //~^ ERROR: mismatched types
+33 | | }
+ | |_^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 30:1
+ --> $DIR/trait-associated-constant.rs:30:1
+ |
+30 | / impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+31 | | const AC: Option<&'c str> = None;
+32 | | //~^ ERROR: mismatched types
+33 | | }
+ | |_^
+
+error[E0308]: mismatched types
+ --> $DIR/trait-associated-constant.rs:38:5
+ |
+38 | const AC: Option<&'a str> = None;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected type `std::option::Option<&'b str>`
+ found type `std::option::Option<&'a str>`
+note: the lifetime 'a as defined on the impl at 37:1...
+ --> $DIR/trait-associated-constant.rs:37:1
+ |
+37 | / impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
+38 | | const AC: Option<&'a str> = None;
+39 | | //~^ ERROR: mismatched types
+40 | | }
+ | |_^
+note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 37:1
+ --> $DIR/trait-associated-constant.rs:37:1
+ |
+37 | / impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
+38 | | const AC: Option<&'a str> = None;
+39 | | //~^ ERROR: mismatched types
+40 | | }
+ | |_^
+
+error: aborting due to 2 previous errors
+