A few cleanups and minor improvements to typeck
This commit is contained in:
parent
6622172734
commit
608c395818
15 changed files with 346 additions and 394 deletions
|
|
@ -147,7 +147,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
bound_region: ty::BrNamed(id, name)
|
||||
}))
|
||||
|
||||
// (*) -- not late-bound, won't change
|
||||
// (*) -- not late-bound, won't change
|
||||
}
|
||||
|
||||
None => {
|
||||
|
|
@ -167,8 +167,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
};
|
||||
|
||||
debug!("ast_region_to_region(lifetime={:?}) yields {:?}",
|
||||
lifetime,
|
||||
r);
|
||||
lifetime,
|
||||
r);
|
||||
|
||||
r
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
span,
|
||||
E0632,
|
||||
"cannot provide explicit type parameters when `impl Trait` is \
|
||||
used in argument position."
|
||||
used in argument position."
|
||||
};
|
||||
|
||||
err.emit();
|
||||
|
|
@ -538,7 +538,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
|
||||
generic_args={:?})",
|
||||
generic_args={:?})",
|
||||
def_id, self_ty, generic_args);
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
|
@ -609,7 +609,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
if default_needs_object_self(param) {
|
||||
struct_span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly \
|
||||
specified",
|
||||
specified",
|
||||
param.name)
|
||||
.span_label(span,
|
||||
format!("missing reference to `{}`", param.name))
|
||||
|
|
@ -623,7 +623,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
self.normalize_ty(
|
||||
span,
|
||||
tcx.at(span).type_of(param.def_id)
|
||||
.subst_spanned(tcx, substs.unwrap(), Some(span))
|
||||
.subst_spanned(tcx, substs.unwrap(), Some(span))
|
||||
).into()
|
||||
}
|
||||
} else if infer_types {
|
||||
|
|
@ -851,7 +851,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
binding.span,
|
||||
E0582,
|
||||
"binding for associated type `{}` references lifetime `{}`, \
|
||||
which does not appear in the trait input types",
|
||||
which does not appear in the trait input types",
|
||||
binding.item_name, br_name)
|
||||
.emit();
|
||||
}
|
||||
|
|
@ -891,7 +891,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
ref_id,
|
||||
binding.span,
|
||||
&format!("associated type binding `{}` specified more than once",
|
||||
binding.item_name)
|
||||
binding.item_name)
|
||||
);
|
||||
err.span_label(binding.span, "used more than once");
|
||||
err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
|
||||
|
|
@ -994,7 +994,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
if !object_safety_violations.is_empty() {
|
||||
tcx.report_object_safety_error(
|
||||
span, principal.def_id(), object_safety_violations)
|
||||
.emit();
|
||||
.emit();
|
||||
return tcx.types.err;
|
||||
}
|
||||
|
||||
|
|
@ -1014,13 +1014,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
for item_def_id in associated_types {
|
||||
let assoc_item = tcx.associated_item(item_def_id);
|
||||
let trait_def_id = assoc_item.container.id();
|
||||
struct_span_err!(tcx.sess, span, E0191,
|
||||
"the value of the associated type `{}` (from the trait `{}`) must be specified",
|
||||
assoc_item.ident,
|
||||
tcx.item_path_str(trait_def_id))
|
||||
.span_label(span, format!(
|
||||
"missing associated type `{}` value", assoc_item.ident))
|
||||
.emit();
|
||||
struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` \
|
||||
(from the trait `{}`) must be specified",
|
||||
assoc_item.ident,
|
||||
tcx.item_path_str(trait_def_id))
|
||||
.span_label(span, format!("missing associated type `{}` value",
|
||||
assoc_item.ident))
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
|
||||
|
|
@ -1032,12 +1032,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
|
||||
.chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
|
||||
.chain(existential_projections
|
||||
.map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
|
||||
.map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
|
||||
.collect::<SmallVec<[_; 8]>>();
|
||||
v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
||||
let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
|
||||
|
||||
|
||||
// Explicitly specified region bound. Use that.
|
||||
let region_bound = if !lifetime.is_elided() {
|
||||
self.ast_region_to_region(lifetime, None)
|
||||
|
|
@ -1072,7 +1071,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type")
|
||||
.span_label(span, "ambiguous associated type")
|
||||
.note(&format!("specify the type using the syntax `<{} as {}>::{}`",
|
||||
type_str, trait_str, name))
|
||||
type_str, trait_str, name))
|
||||
.emit();
|
||||
|
||||
}
|
||||
|
|
@ -1094,8 +1093,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
|
||||
// Check that there is exactly one way to find an associated type with the
|
||||
// correct name.
|
||||
let suitable_bounds =
|
||||
traits::transitive_bounds(tcx, &bounds)
|
||||
let suitable_bounds = traits::transitive_bounds(tcx, &bounds)
|
||||
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name));
|
||||
|
||||
let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap();
|
||||
|
|
@ -1110,10 +1108,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
// Checks that bounds contains exactly one element and reports appropriate
|
||||
// errors otherwise.
|
||||
fn one_bound_for_assoc_type<I>(&self,
|
||||
mut bounds: I,
|
||||
ty_param_name: &str,
|
||||
assoc_name: ast::Ident,
|
||||
span: Span)
|
||||
mut bounds: I,
|
||||
ty_param_name: &str,
|
||||
assoc_name: ast::Ident,
|
||||
span: Span)
|
||||
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
|
||||
where I: Iterator<Item=ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
|
|
@ -1121,9 +1119,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
Some(bound) => bound,
|
||||
None => {
|
||||
struct_span_err!(self.tcx().sess, span, E0220,
|
||||
"associated type `{}` not found for `{}`",
|
||||
assoc_name,
|
||||
ty_param_name)
|
||||
"associated type `{}` not found for `{}`",
|
||||
assoc_name,
|
||||
ty_param_name)
|
||||
.span_label(span, format!("associated type `{}` not found", assoc_name))
|
||||
.emit();
|
||||
return Err(ErrorReported);
|
||||
|
|
@ -1142,14 +1140,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
for bound in bounds {
|
||||
let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| {
|
||||
item.kind == ty::AssociatedKind::Type &&
|
||||
self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
|
||||
self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
|
||||
})
|
||||
.and_then(|item| self.tcx().hir.span_if_local(item.def_id));
|
||||
|
||||
if let Some(span) = bound_span {
|
||||
err.span_label(span, format!("ambiguous `{}` from `{}`",
|
||||
assoc_name,
|
||||
bound));
|
||||
assoc_name,
|
||||
bound));
|
||||
} else {
|
||||
span_note!(&mut err, span,
|
||||
"associated type `{}` could derive from `{}`",
|
||||
|
|
@ -1198,8 +1196,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
};
|
||||
|
||||
let candidates =
|
||||
traits::supertraits(tcx, ty::Binder::bind(trait_ref))
|
||||
let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref))
|
||||
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
|
||||
|
||||
match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) {
|
||||
|
|
@ -1230,7 +1227,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id);
|
||||
let item = tcx.associated_items(trait_did).find(|i| {
|
||||
Namespace::from(i.kind) == Namespace::Type &&
|
||||
i.ident.modern() == assoc_ident
|
||||
i.ident.modern() == assoc_ident
|
||||
})
|
||||
.expect("missing associated type");
|
||||
|
||||
|
|
@ -1293,8 +1290,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
if err_for_lt { continue }
|
||||
err_for_lt = true;
|
||||
(struct_span_err!(self.tcx().sess, lt.span, E0110,
|
||||
"lifetime parameters are not allowed on \
|
||||
this type"),
|
||||
"lifetime parameters are not allowed on this type"),
|
||||
lt.span,
|
||||
"lifetime")
|
||||
}
|
||||
|
|
@ -1302,7 +1298,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
if err_for_ty { continue }
|
||||
err_for_ty = true;
|
||||
(struct_span_err!(self.tcx().sess, ty.span, E0109,
|
||||
"type parameters are not allowed on this type"),
|
||||
"type parameters are not allowed on this type"),
|
||||
ty.span,
|
||||
"type")
|
||||
}
|
||||
|
|
@ -1590,7 +1586,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
|||
));
|
||||
|
||||
// Find any late-bound regions declared in return type that do
|
||||
// not appear in the arguments. These are not wellformed.
|
||||
// not appear in the arguments. These are not well-formed.
|
||||
//
|
||||
// Example:
|
||||
// for<'a> fn() -> &'a str <-- 'a is bad
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
|
|||
let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
format!("unused import: `{}`", snippet)
|
||||
} else {
|
||||
"unused import".to_string()
|
||||
"unused import".to_owned()
|
||||
};
|
||||
self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,33 +55,29 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
|
||||
match tcx.type_of(impl_did).sty {
|
||||
ty::Adt(..) => {}
|
||||
_ => {
|
||||
// Destructors only work on nominal types.
|
||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) {
|
||||
match tcx.hir.find(impl_node_id) {
|
||||
Some(Node::Item(item)) => {
|
||||
let span = match item.node {
|
||||
ItemKind::Impl(.., ref ty, _) => ty.span,
|
||||
_ => item.span,
|
||||
};
|
||||
struct_span_err!(tcx.sess,
|
||||
span,
|
||||
E0120,
|
||||
"the Drop trait may only be implemented on \
|
||||
structures")
|
||||
.span_label(span, "implementing Drop requires a struct")
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
bug!("didn't find impl in ast map");
|
||||
}
|
||||
}
|
||||
if let ty::Adt(..) = tcx.type_of(impl_did).sty {
|
||||
/* do nothing */
|
||||
} else {
|
||||
// Destructors only work on nominal types.
|
||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) {
|
||||
if let Some(Node::Item(item)) = tcx.hir.find(impl_node_id) {
|
||||
let span = match item.node {
|
||||
ItemKind::Impl(.., ref ty, _) => ty.span,
|
||||
_ => item.span,
|
||||
};
|
||||
struct_span_err!(tcx.sess,
|
||||
span,
|
||||
E0120,
|
||||
"the Drop trait may only be implemented on \
|
||||
structures")
|
||||
.span_label(span, "implementing Drop requires a struct")
|
||||
.emit();
|
||||
} else {
|
||||
bug!("found external impl of Drop trait on \
|
||||
something other than a struct");
|
||||
bug!("didn't find impl in ast map");
|
||||
}
|
||||
} else {
|
||||
bug!("found external impl of Drop trait on \
|
||||
something other than a struct");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,8 +88,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:
|
|||
let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) {
|
||||
n
|
||||
} else {
|
||||
debug!("visit_implementation_of_copy(): impl not in this \
|
||||
crate");
|
||||
debug!("visit_implementation_of_copy(): impl not in this crate");
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -119,11 +114,11 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:
|
|||
};
|
||||
|
||||
let mut err = struct_span_err!(tcx.sess,
|
||||
span,
|
||||
E0204,
|
||||
"the trait `Copy` may not be implemented for this type");
|
||||
span,
|
||||
E0204,
|
||||
"the trait `Copy` may not be implemented for this type");
|
||||
for span in fields.iter().map(|f| tcx.def_span(f.did)) {
|
||||
err.span_label(span, "this field does not implement `Copy`");
|
||||
err.span_label(span, "this field does not implement `Copy`");
|
||||
}
|
||||
err.emit()
|
||||
}
|
||||
|
|
@ -173,12 +168,9 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
|
||||
let coerce_unsized_trait = gcx.lang_items().coerce_unsized_trait().unwrap();
|
||||
|
||||
let unsize_trait = match gcx.lang_items().require(UnsizeTraitLangItem) {
|
||||
Ok(id) => id,
|
||||
Err(err) => {
|
||||
gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
|
||||
}
|
||||
};
|
||||
let unsize_trait = gcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| {
|
||||
gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
|
||||
});
|
||||
|
||||
// this provider should only get invoked for local def-ids
|
||||
let impl_node_id = gcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
|
||||
|
|
@ -210,9 +202,9 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
mk_ptr: &dyn Fn(Ty<'gcx>) -> Ty<'gcx>| {
|
||||
if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
|
||||
infcx.report_mismatched_types(&cause,
|
||||
mk_ptr(mt_b.ty),
|
||||
target,
|
||||
ty::error::TypeError::Mutability)
|
||||
mk_ptr(mt_b.ty),
|
||||
target,
|
||||
ty::error::TypeError::Mutability)
|
||||
.emit();
|
||||
}
|
||||
(mt_a.ty, mt_b.ty, unsize_trait, None)
|
||||
|
|
@ -235,7 +227,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
}
|
||||
|
||||
(&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() &&
|
||||
def_b.is_struct() => {
|
||||
def_b.is_struct() => {
|
||||
if def_a != def_b {
|
||||
let source_path = gcx.item_path_str(def_a.did);
|
||||
let target_path = gcx.item_path_str(def_b.did);
|
||||
|
|
|
|||
|
|
@ -315,8 +315,7 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
|
|||
E0116,
|
||||
"cannot define inherent `impl` for a type outside of the crate \
|
||||
where the type is defined")
|
||||
.span_label(item.span,
|
||||
"impl for type defined outside of crate.")
|
||||
.span_label(item.span, "impl for type defined outside of crate.")
|
||||
.note("define and implement a trait or new type instead")
|
||||
.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
|
|||
|
||||
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
|
||||
debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
|
||||
trait_ref,
|
||||
tcx.item_path_str(impl_def_id));
|
||||
trait_ref,
|
||||
tcx.item_path_str(impl_def_id));
|
||||
|
||||
// Skip impls where one of the self type is an error type.
|
||||
// This occurs with e.g. resolve failures (#30589).
|
||||
|
|
|
|||
|
|
@ -33,130 +33,125 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
|
|||
/// reports.
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||
match item.node {
|
||||
hir::ItemKind::Impl(.., Some(_), _, _) => {
|
||||
// "Trait" impl
|
||||
debug!("coherence2::orphan check: trait impl {}",
|
||||
self.tcx.hir.node_to_string(item.id));
|
||||
let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
let cm = self.tcx.sess.source_map();
|
||||
let sp = cm.def_span(item.span);
|
||||
match traits::orphan_check(self.tcx, def_id) {
|
||||
Ok(()) => {}
|
||||
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
sp,
|
||||
E0117,
|
||||
"only traits defined in the current crate can be \
|
||||
implemented for arbitrary types")
|
||||
.span_label(sp, "impl doesn't use types inside crate")
|
||||
.note("the impl does not reference any types defined in this crate")
|
||||
.note("define and implement a trait or new type instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
sp,
|
||||
E0210,
|
||||
"type parameter `{}` must be used as the type parameter \
|
||||
for some local type (e.g. `MyStruct<{}>`)",
|
||||
param_ty,
|
||||
param_ty)
|
||||
.span_label(sp,
|
||||
format!("type parameter `{}` must be used as the type \
|
||||
parameter for some local type", param_ty))
|
||||
.note("only traits defined in the current crate can be implemented \
|
||||
for a type parameter")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
// "Trait" impl
|
||||
if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
|
||||
debug!("coherence2::orphan check: trait impl {}",
|
||||
self.tcx.hir.node_to_string(item.id));
|
||||
let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
let cm = self.tcx.sess.source_map();
|
||||
let sp = cm.def_span(item.span);
|
||||
match traits::orphan_check(self.tcx, def_id) {
|
||||
Ok(()) => {}
|
||||
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
sp,
|
||||
E0117,
|
||||
"only traits defined in the current crate can be \
|
||||
implemented for arbitrary types")
|
||||
.span_label(sp, "impl doesn't use types inside crate")
|
||||
.note("the impl does not reference any types defined in this crate")
|
||||
.note("define and implement a trait or new type instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
// In addition to the above rules, we restrict impls of auto traits
|
||||
// so that they can only be implemented on nominal types, such as structs,
|
||||
// enums or foreign types. To see why this restriction exists, consider the
|
||||
// following example (#22978). Imagine that crate A defines an auto trait
|
||||
// `Foo` and a fn that operates on pairs of types:
|
||||
//
|
||||
// ```
|
||||
// // Crate A
|
||||
// auto trait Foo { }
|
||||
// fn two_foos<A:Foo,B:Foo>(..) {
|
||||
// one_foo::<(A,B)>(..)
|
||||
// }
|
||||
// fn one_foo<T:Foo>(..) { .. }
|
||||
// ```
|
||||
//
|
||||
// This type-checks fine; in particular the fn
|
||||
// `two_foos` is able to conclude that `(A,B):Foo`
|
||||
// because `A:Foo` and `B:Foo`.
|
||||
//
|
||||
// Now imagine that crate B comes along and does the following:
|
||||
//
|
||||
// ```
|
||||
// struct A { }
|
||||
// struct B { }
|
||||
// impl Foo for A { }
|
||||
// impl Foo for B { }
|
||||
// impl !Send for (A, B) { }
|
||||
// ```
|
||||
//
|
||||
// This final impl is legal according to the orpan
|
||||
// rules, but it invalidates the reasoning from
|
||||
// `two_foos` above.
|
||||
debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
|
||||
trait_ref,
|
||||
trait_def_id,
|
||||
self.tcx.trait_is_auto(trait_def_id));
|
||||
if self.tcx.trait_is_auto(trait_def_id) &&
|
||||
!trait_def_id.is_local() {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let opt_self_def_id = match self_ty.sty {
|
||||
ty::Adt(self_def, _) => Some(self_def.did),
|
||||
ty::Foreign(did) => Some(did),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let msg = match opt_self_def_id {
|
||||
// We only want to permit nominal types, but not *all* nominal types.
|
||||
// They must be local to the current crate, so that people
|
||||
// can't do `unsafe impl Send for Rc<SomethingLocal>` or
|
||||
// `impl !Send for Box<SomethingLocalAndSend>`.
|
||||
Some(self_def_id) => {
|
||||
if self_def_id.is_local() {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
format!("cross-crate traits with a default impl, like `{}`, \
|
||||
can only be implemented for a struct/enum type \
|
||||
defined in the current crate",
|
||||
self.tcx.item_path_str(trait_def_id)),
|
||||
"can't implement cross-crate trait for type in another crate"
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Some((format!("cross-crate traits with a default impl, like `{}`, can \
|
||||
only be implemented for a struct/enum type, not `{}`",
|
||||
self.tcx.item_path_str(trait_def_id),
|
||||
self_ty),
|
||||
"can't implement cross-crate trait with a default impl for \
|
||||
non-struct/enum type"))
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((msg, label)) = msg {
|
||||
struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
|
||||
.span_label(sp, label)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
sp,
|
||||
E0210,
|
||||
"type parameter `{}` must be used as the type parameter \
|
||||
for some local type (e.g. `MyStruct<{}>`)",
|
||||
param_ty,
|
||||
param_ty)
|
||||
.span_label(sp,
|
||||
format!("type parameter `{}` must be used as the type \
|
||||
parameter for some local type", param_ty))
|
||||
.note("only traits defined in the current crate can be implemented \
|
||||
for a type parameter")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Not an impl
|
||||
|
||||
// In addition to the above rules, we restrict impls of auto traits
|
||||
// so that they can only be implemented on nominal types, such as structs,
|
||||
// enums or foreign types. To see why this restriction exists, consider the
|
||||
// following example (#22978). Imagine that crate A defines an auto trait
|
||||
// `Foo` and a fn that operates on pairs of types:
|
||||
//
|
||||
// ```
|
||||
// // Crate A
|
||||
// auto trait Foo { }
|
||||
// fn two_foos<A:Foo,B:Foo>(..) {
|
||||
// one_foo::<(A,B)>(..)
|
||||
// }
|
||||
// fn one_foo<T:Foo>(..) { .. }
|
||||
// ```
|
||||
//
|
||||
// This type-checks fine; in particular the fn
|
||||
// `two_foos` is able to conclude that `(A,B):Foo`
|
||||
// because `A:Foo` and `B:Foo`.
|
||||
//
|
||||
// Now imagine that crate B comes along and does the following:
|
||||
//
|
||||
// ```
|
||||
// struct A { }
|
||||
// struct B { }
|
||||
// impl Foo for A { }
|
||||
// impl Foo for B { }
|
||||
// impl !Send for (A, B) { }
|
||||
// ```
|
||||
//
|
||||
// This final impl is legal according to the orpan
|
||||
// rules, but it invalidates the reasoning from
|
||||
// `two_foos` above.
|
||||
debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
|
||||
trait_ref,
|
||||
trait_def_id,
|
||||
self.tcx.trait_is_auto(trait_def_id));
|
||||
if self.tcx.trait_is_auto(trait_def_id) &&
|
||||
!trait_def_id.is_local() {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let opt_self_def_id = match self_ty.sty {
|
||||
ty::Adt(self_def, _) => Some(self_def.did),
|
||||
ty::Foreign(did) => Some(did),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let msg = match opt_self_def_id {
|
||||
// We only want to permit nominal types, but not *all* nominal types.
|
||||
// They must be local to the current crate, so that people
|
||||
// can't do `unsafe impl Send for Rc<SomethingLocal>` or
|
||||
// `impl !Send for Box<SomethingLocalAndSend>`.
|
||||
Some(self_def_id) => {
|
||||
if self_def_id.is_local() {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
format!("cross-crate traits with a default impl, like `{}`, \
|
||||
can only be implemented for a struct/enum type \
|
||||
defined in the current crate",
|
||||
self.tcx.item_path_str(trait_def_id)),
|
||||
"can't implement cross-crate trait for type in another crate"
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Some((format!("cross-crate traits with a default impl, like `{}`, can \
|
||||
only be implemented for a struct/enum type, not `{}`",
|
||||
self.tcx.item_path_str(trait_def_id),
|
||||
self_ty),
|
||||
"can't implement cross-crate trait with a default impl for \
|
||||
non-struct/enum type"))
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((msg, label)) = msg {
|
||||
struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
|
||||
.span_label(sp, label)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,52 +29,49 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
|
|||
item: &'v hir::Item,
|
||||
impl_generics: Option<&hir::Generics>,
|
||||
unsafety: hir::Unsafety,
|
||||
polarity: hir::ImplPolarity) {
|
||||
match self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) {
|
||||
None => {}
|
||||
polarity: hir::ImplPolarity)
|
||||
{
|
||||
if let Some(trait_ref) = self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) {
|
||||
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||
let unsafe_attr = impl_generics.and_then(|generics| {
|
||||
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
|
||||
});
|
||||
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
|
||||
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0199,
|
||||
"implementing the trait `{}` is not unsafe",
|
||||
trait_ref);
|
||||
}
|
||||
|
||||
Some(trait_ref) => {
|
||||
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||
let unsafe_attr = impl_generics.and_then(|generics| {
|
||||
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
|
||||
});
|
||||
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
|
||||
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0199,
|
||||
"implementing the trait `{}` is not unsafe",
|
||||
trait_ref);
|
||||
}
|
||||
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0200,
|
||||
"the trait `{}` requires an `unsafe impl` declaration",
|
||||
trait_ref);
|
||||
}
|
||||
|
||||
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0200,
|
||||
"the trait `{}` requires an `unsafe impl` declaration",
|
||||
trait_ref);
|
||||
}
|
||||
(Unsafety::Normal, Some(attr_name), Unsafety::Normal,
|
||||
hir::ImplPolarity::Positive) =>
|
||||
{
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0569,
|
||||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||
attr_name);
|
||||
}
|
||||
|
||||
(Unsafety::Normal, Some(attr_name), Unsafety::Normal,
|
||||
hir::ImplPolarity::Positive) =>
|
||||
{
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0569,
|
||||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||
attr_name);
|
||||
}
|
||||
|
||||
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
|
||||
// Reported in AST validation
|
||||
self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
|
||||
}
|
||||
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
|
||||
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||
(Unsafety::Normal, None, Unsafety::Normal, _) => {
|
||||
// OK
|
||||
}
|
||||
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
|
||||
// Reported in AST validation
|
||||
self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
|
||||
}
|
||||
(_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
|
||||
(Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||
(Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
|
||||
(Unsafety::Normal, None, Unsafety::Normal, _) => {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,11 +80,8 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
|
|||
|
||||
impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'v hir::Item) {
|
||||
match item.node {
|
||||
hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) => {
|
||||
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
|
||||
}
|
||||
_ => {}
|
||||
if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.node {
|
||||
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ use std::iter;
|
|||
pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let mut visitor = CollectItemTypesVisitor { tcx: tcx };
|
||||
tcx.hir
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
@ -197,7 +197,8 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
|||
E0121,
|
||||
"the type placeholder `_` is not allowed within types on item signatures"
|
||||
).span_label(span, "not allowed in type signatures")
|
||||
.emit();
|
||||
.emit();
|
||||
|
||||
self.tcx().types.err
|
||||
}
|
||||
|
||||
|
|
@ -529,12 +530,11 @@ fn convert_enum_variant_types<'a, 'tcx>(
|
|||
).span_label(
|
||||
variant.span,
|
||||
format!("overflowed on value after {}", prev_discr.unwrap()),
|
||||
)
|
||||
.note(&format!(
|
||||
"explicitly set `{} = {}` if that is desired outcome",
|
||||
variant.node.name, wrapped_discr
|
||||
))
|
||||
.emit();
|
||||
).note(&format!(
|
||||
"explicitly set `{} = {}` if that is desired outcome",
|
||||
variant.node.name, wrapped_discr
|
||||
))
|
||||
.emit();
|
||||
None
|
||||
}.unwrap_or(wrapped_discr),
|
||||
);
|
||||
|
|
@ -577,8 +577,8 @@ fn convert_variant<'a, 'tcx>(
|
|||
"field `{}` is already declared",
|
||||
f.ident
|
||||
).span_label(f.span, "field already declared")
|
||||
.span_label(prev_span, format!("`{}` first declared here", f.ident))
|
||||
.emit();
|
||||
.span_label(prev_span, format!("`{}` first declared here", f.ident))
|
||||
.emit();
|
||||
} else {
|
||||
seen_fields.insert(f.ident.modern(), f.span);
|
||||
}
|
||||
|
|
@ -824,14 +824,11 @@ fn has_late_bound_regions<'a, 'tcx>(
|
|||
has_late_bound_regions: None,
|
||||
};
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
let hir_id = tcx.hir.node_to_hir_id(param.id);
|
||||
if tcx.is_late_bound(hir_id) {
|
||||
return Some(param.span);
|
||||
}
|
||||
if let GenericParamKind::Lifetime { .. } = param.kind {
|
||||
let hir_id = tcx.hir.node_to_hir_id(param.id);
|
||||
if tcx.is_late_bound(hir_id) {
|
||||
return Some(param.span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
visitor.visit_fn_decl(decl);
|
||||
|
|
@ -1314,6 +1311,7 @@ fn find_existential_constraints<'a, 'tcx>(
|
|||
def_id: DefId,
|
||||
found: Option<(Span, ty::Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> {
|
||||
fn check(&mut self, def_id: DefId) {
|
||||
trace!("checking {:?}", def_id);
|
||||
|
|
@ -1347,6 +1345,7 @@ fn find_existential_constraints<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'a, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
|
||||
intravisit::NestedVisitorMap::All(&self.tcx.hir)
|
||||
|
|
@ -1373,6 +1372,7 @@ fn find_existential_constraints<'a, 'tcx>(
|
|||
intravisit::walk_trait_item(self, it);
|
||||
}
|
||||
}
|
||||
|
||||
let mut locator = ConstraintLocator {
|
||||
def_id,
|
||||
tcx,
|
||||
|
|
@ -1380,7 +1380,9 @@ fn find_existential_constraints<'a, 'tcx>(
|
|||
};
|
||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
let parent = tcx.hir.get_parent(node_id);
|
||||
|
||||
trace!("parent_id: {:?}", parent);
|
||||
|
||||
if parent == ast::CRATE_NODE_ID {
|
||||
intravisit::walk_crate(&mut locator, tcx.hir.krate());
|
||||
} else {
|
||||
|
|
@ -1395,6 +1397,7 @@ fn find_existential_constraints<'a, 'tcx>(
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
match locator.found {
|
||||
Some((_, ty)) => ty,
|
||||
None => {
|
||||
|
|
@ -1786,17 +1789,14 @@ fn explicit_predicates_of<'a, 'tcx>(
|
|||
// Collect the predicates that were written inline by the user on each
|
||||
// type parameter (e.g., `<T:Foo>`).
|
||||
for param in &ast_generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Type { .. } => {
|
||||
let name = param.name.ident().as_interned_str();
|
||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
||||
index += 1;
|
||||
if let GenericParamKind::Type { .. } = param.kind {
|
||||
let name = param.name.ident().as_interned_str();
|
||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
||||
index += 1;
|
||||
|
||||
let sized = SizedByDefault::Yes;
|
||||
let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
}
|
||||
_ => {}
|
||||
let sized = SizedByDefault::Yes;
|
||||
let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1835,10 +1835,10 @@ fn explicit_predicates_of<'a, 'tcx>(
|
|||
&mut projections,
|
||||
);
|
||||
|
||||
predicates.push((trait_ref.to_predicate(), poly_trait_ref.span));
|
||||
predicates.extend(projections.iter().map(|&(p, span)| {
|
||||
(p.to_predicate(), span)
|
||||
}));
|
||||
predicates.extend(
|
||||
iter::once((trait_ref.to_predicate(), poly_trait_ref.span)).chain(
|
||||
projections.iter().map(|&(p, span)| (p.to_predicate(), span)
|
||||
)));
|
||||
}
|
||||
|
||||
&hir::GenericBound::Outlives(ref lifetime) => {
|
||||
|
|
@ -1852,7 +1852,7 @@ fn explicit_predicates_of<'a, 'tcx>(
|
|||
|
||||
&hir::WherePredicate::RegionPredicate(ref region_pred) => {
|
||||
let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None);
|
||||
for bound in ®ion_pred.bounds {
|
||||
predicates.extend(region_pred.bounds.iter().map(|bound| {
|
||||
let (r2, span) = match bound {
|
||||
hir::GenericBound::Outlives(lt) => {
|
||||
(AstConv::ast_region_to_region(&icx, lt, None), lt.span)
|
||||
|
|
@ -1860,8 +1860,9 @@ fn explicit_predicates_of<'a, 'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
|
||||
predicates.push((ty::Predicate::RegionOutlives(pred), span))
|
||||
}
|
||||
|
||||
(ty::Predicate::RegionOutlives(pred), span)
|
||||
}))
|
||||
}
|
||||
|
||||
&hir::WherePredicate::EqPredicate(..) => {
|
||||
|
|
@ -1876,9 +1877,7 @@ fn explicit_predicates_of<'a, 'tcx>(
|
|||
let trait_item = tcx.hir.trait_item(trait_item_ref.id);
|
||||
let bounds = match trait_item.node {
|
||||
hir::TraitItemKind::Type(ref bounds, _) => bounds,
|
||||
_ => {
|
||||
return vec![].into_iter();
|
||||
}
|
||||
_ => return vec![].into_iter()
|
||||
};
|
||||
|
||||
let assoc_ty =
|
||||
|
|
@ -1939,6 +1938,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
|||
) -> Bounds<'tcx> {
|
||||
let mut region_bounds = vec![];
|
||||
let mut trait_bounds = vec![];
|
||||
|
||||
for ast_bound in ast_bounds {
|
||||
match *ast_bound {
|
||||
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b),
|
||||
|
|
@ -2032,16 +2032,16 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
|
|||
let check = |ast_ty: &hir::Ty, ty: Ty| {
|
||||
if ty.is_simd() {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
ast_ty.span,
|
||||
&format!(
|
||||
"use of SIMD type `{}` in FFI is highly experimental and \
|
||||
may result in invalid code",
|
||||
tcx.hir.node_to_pretty_string(ast_ty.id)
|
||||
),
|
||||
)
|
||||
.help("add #![feature(simd_ffi)] to the crate attributes to enable")
|
||||
.emit();
|
||||
.struct_span_err(
|
||||
ast_ty.span,
|
||||
&format!(
|
||||
"use of SIMD type `{}` in FFI is highly experimental and \
|
||||
may result in invalid code",
|
||||
tcx.hir.node_to_pretty_string(ast_ty.id)
|
||||
),
|
||||
)
|
||||
.help("add #![feature(simd_ffi)] to the crate attributes to enable")
|
||||
.emit();
|
||||
}
|
||||
};
|
||||
for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) {
|
||||
|
|
@ -2101,7 +2101,7 @@ fn from_target_feature(
|
|||
};
|
||||
|
||||
// We allow comma separation to enable multiple features
|
||||
for feature in value.as_str().split(',') {
|
||||
target_features.extend(value.as_str().split(',').filter_map(|feature| {
|
||||
// Only allow whitelisted features per platform
|
||||
let feature_gate = match whitelist.get(feature) {
|
||||
Some(g) => g,
|
||||
|
|
@ -2120,7 +2120,7 @@ fn from_target_feature(
|
|||
}
|
||||
}
|
||||
err.emit();
|
||||
continue;
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2147,10 +2147,10 @@ fn from_target_feature(
|
|||
feature_gate::GateIssue::Language,
|
||||
&format!("the target feature `{}` is currently unstable", feature),
|
||||
);
|
||||
continue;
|
||||
return None;
|
||||
}
|
||||
target_features.push(Symbol::intern(feature));
|
||||
}
|
||||
Some(Symbol::intern(feature))
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2183,7 +2183,7 @@ fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: &
|
|||
tcx.sess.span_fatal(span, "invalid linkage specified")
|
||||
} else {
|
||||
tcx.sess
|
||||
.fatal(&format!("invalid linkage specified: {}", name))
|
||||
.fatal(&format!("invalid linkage specified: {}", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2281,7 +2281,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
|
|||
E0558,
|
||||
"`export_name` attribute has invalid format"
|
||||
).span_label(attr.span, "did you mean #[export_name=\"*\"]?")
|
||||
.emit();
|
||||
.emit();
|
||||
}
|
||||
} else if attr.check_name("target_feature") {
|
||||
if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
|
||||
|
|
|
|||
|
|
@ -77,11 +77,8 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
|||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||
match *r {
|
||||
ty::ReEarlyBound(data) => {
|
||||
self.parameters.push(Parameter::from(data));
|
||||
}
|
||||
_ => {}
|
||||
if let ty::ReEarlyBound(data) = *r {
|
||||
self.parameters.push(Parameter::from(data));
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -204,6 +201,6 @@ pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt,
|
|||
}
|
||||
debug!("setup_constraining_predicates: predicates={:?} \
|
||||
i={} impl_trait_ref={:?} input_parameters={:?}",
|
||||
predicates, i, impl_trait_ref, input_parameters);
|
||||
predicates, i, impl_trait_ref, input_parameters);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,15 +71,12 @@ struct ImplWfCheck<'a, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||
match item.node {
|
||||
hir::ItemKind::Impl(.., ref impl_item_refs) => {
|
||||
let impl_def_id = self.tcx.hir.local_def_id(item.id);
|
||||
enforce_impl_params_are_constrained(self.tcx,
|
||||
impl_def_id,
|
||||
impl_item_refs);
|
||||
enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
|
||||
}
|
||||
_ => { }
|
||||
if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.node {
|
||||
let impl_def_id = self.tcx.hir.local_def_id(item.id);
|
||||
enforce_impl_params_are_constrained(self.tcx,
|
||||
impl_def_id,
|
||||
impl_item_refs);
|
||||
enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +179,7 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let impl_item = tcx.hir.impl_item(impl_item_ref.id);
|
||||
let seen_items = match impl_item.node {
|
||||
hir::ImplItemKind::Type(_) => &mut seen_type_items,
|
||||
_ => &mut seen_value_items,
|
||||
_ => &mut seen_value_items,
|
||||
};
|
||||
match seen_items.entry(impl_item.ident.modern()) {
|
||||
Occupied(entry) => {
|
||||
|
|
@ -191,7 +188,7 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl_item.ident);
|
||||
err.span_label(*entry.get(),
|
||||
format!("previous definition of `{}` here",
|
||||
impl_item.ident));
|
||||
impl_item.ident));
|
||||
err.span_label(impl_item.span, "duplicate definition");
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
|
|||
span: Span) {
|
||||
if decl.variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0045,
|
||||
"variadic function must have C or cdecl calling convention");
|
||||
"variadic function must have C or cdecl calling convention");
|
||||
err.span_label(span, "variadics require C or cdecl calling convention").emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -186,35 +186,29 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let main_t = tcx.type_of(main_def_id);
|
||||
match main_t.sty {
|
||||
ty::FnDef(..) => {
|
||||
match tcx.hir.find(main_id) {
|
||||
Some(Node::Item(it)) => {
|
||||
match it.node {
|
||||
hir::ItemKind::Fn(.., ref generics, _) => {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
let msg = "`main` function is not allowed to have generic \
|
||||
parameters".to_string();
|
||||
let label = "`main` cannot have generic parameters".to_string();
|
||||
struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
|
||||
.span_label(generics.span, label)
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if let Some(sp) = generics.where_clause.span() {
|
||||
struct_span_err!(tcx.sess, sp, E0646,
|
||||
"`main` function is not allowed to have a `where` clause")
|
||||
.span_label(sp, "`main` cannot have a `where` clause")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if error {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
if let Some(Node::Item(it)) = tcx.hir.find(main_id) {
|
||||
if let hir::ItemKind::Fn(.., ref generics, _) = it.node {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
let msg = "`main` function is not allowed to have generic \
|
||||
parameters".to_owned();
|
||||
let label = "`main` cannot have generic parameters".to_string();
|
||||
struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
|
||||
.span_label(generics.span, label)
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if let Some(sp) = generics.where_clause.span() {
|
||||
struct_span_err!(tcx.sess, sp, E0646,
|
||||
"`main` function is not allowed to have a `where` clause")
|
||||
.span_label(sp, "`main` cannot have a `where` clause")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if error {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let actual = tcx.fn_sig(main_def_id);
|
||||
|
|
@ -258,34 +252,28 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let start_t = tcx.type_of(start_def_id);
|
||||
match start_t.sty {
|
||||
ty::FnDef(..) => {
|
||||
match tcx.hir.find(start_id) {
|
||||
Some(Node::Item(it)) => {
|
||||
match it.node {
|
||||
hir::ItemKind::Fn(.., ref generics, _) => {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
struct_span_err!(tcx.sess, generics.span, E0132,
|
||||
"start function is not allowed to have type parameters")
|
||||
.span_label(generics.span,
|
||||
"start function cannot have type parameters")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if let Some(sp) = generics.where_clause.span() {
|
||||
struct_span_err!(tcx.sess, sp, E0647,
|
||||
"start function is not allowed to have a `where` clause")
|
||||
.span_label(sp, "start function cannot have a `where` clause")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if error {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
if let Some(Node::Item(it)) = tcx.hir.find(start_id) {
|
||||
if let hir::ItemKind::Fn(.., ref generics, _) = it.node {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
struct_span_err!(tcx.sess, generics.span, E0132,
|
||||
"start function is not allowed to have type parameters")
|
||||
.span_label(generics.span,
|
||||
"start function cannot have type parameters")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if let Some(sp) = generics.where_clause.span() {
|
||||
struct_span_err!(tcx.sess, sp, E0647,
|
||||
"start function is not allowed to have a `where` clause")
|
||||
.span_label(sp, "start function cannot have a `where` clause")
|
||||
.emit();
|
||||
error = true;
|
||||
}
|
||||
if error {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
|
||||
|
|
@ -388,6 +376,7 @@ pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) ->
|
|||
let env_node_id = tcx.hir.get_parent(hir_ty.id);
|
||||
let env_def_id = tcx.hir.local_def_id(env_node_id);
|
||||
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
|
||||
|
||||
astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
|
||||
}
|
||||
|
||||
|
|
@ -403,6 +392,7 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait:
|
|||
let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
|
||||
&item_cx, hir_trait, tcx.types.err, &mut projections, true
|
||||
);
|
||||
|
||||
(principal, projections)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,7 @@ fn inferred_outlives_of<'a, 'tcx>(
|
|||
.iter()
|
||||
.map(|out_pred| match out_pred {
|
||||
ty::Predicate::RegionOutlives(p) => p.to_string(),
|
||||
|
||||
ty::Predicate::TypeOutlives(p) => p.to_string(),
|
||||
|
||||
err => bug!("unexpected predicate {:?}", err),
|
||||
}).collect();
|
||||
pred.sort();
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use rustc::ty::TyCtxt;
|
|||
|
||||
pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
tcx.hir
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut OutlivesTest { tcx });
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut OutlivesTest { tcx });
|
||||
}
|
||||
|
||||
struct OutlivesTest<'a, 'tcx: 'a> {
|
||||
|
|
|
|||
|
|
@ -148,15 +148,9 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
|
|||
// field: &'static T, // this would generate a ReStatic
|
||||
// }
|
||||
RegionKind::ReStatic => {
|
||||
if tcx
|
||||
.sess
|
||||
.features_untracked()
|
||||
.infer_static_outlives_requirements
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
tcx.sess
|
||||
.features_untracked()
|
||||
.infer_static_outlives_requirements
|
||||
}
|
||||
|
||||
// Late-bound regions can appear in `fn` types:
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
|
|||
}
|
||||
|
||||
fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
|
||||
-> Lrc<Vec<ty::Variance>> {
|
||||
-> Lrc<Vec<ty::Variance>> {
|
||||
let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
|
||||
let unsupported = || {
|
||||
// Variance not relevant.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue