Skip to content

A few cleanups and minor improvements to typeck #54591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 30, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 35 additions & 39 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someday we should probably get rustfmt working on this codebase (which might require some special tooling; compare #53896). I unambiguously agree with most of the spacing changes in this PR, but where my personal æsthetics happen to disagree (here, I would treat the format varargs the same as the other arguments to struct_span_err! rather than aligning them to the format string), I tend to doubt that that degree of bikeshedding is part of my duty as a reviewer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess at one point whitespace tidying will become automated; just I adjust some spots as I go to what I feel looks more readable and hope I'm not the one who feels that way 😜.

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,20 +1108,20 @@ 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>>
{
let bound = match bounds.next() {
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,16 +1290,15 @@ 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")
}
hir::GenericArg::Type(ty) => {
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
2 changes: 1 addition & 1 deletion src/librustc_typeck/check_unused.rs
Original file line number Diff line number Diff line change
@@ -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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also prefer .to_owned over .to_string for literals (the former indicates that we're getting ownership of something which is already a string in some sense of the word, whereas the latter could be anything Display-able), but it's possible that we're in the minority insofar as The Book recommends .to_string or String::from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think The Book just recommends the solution that is simplest to grasp and remember; to_string calls String::from which, in turn, calls to_owned(), so everything boils down to to_owned anyways.

};
self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
}
74 changes: 33 additions & 41 deletions src/librustc_typeck/coherence/builtin.rs
Original file line number Diff line number Diff line change
@@ -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);
3 changes: 1 addition & 2 deletions src/librustc_typeck/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
@@ -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();
}
4 changes: 2 additions & 2 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
@@ -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).
231 changes: 113 additions & 118 deletions src/librustc_typeck/coherence/orphan.rs
Original file line number Diff line number Diff line change
@@ -33,131 +33,126 @@ 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;
}
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;
}
}

// 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,
};
// 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"))
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"
))
}
};

if let Some((msg, label)) = msg {
struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
.span_label(sp, label)
.emit();
return;
}
_ => {
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;
}
}
_ => {
// Not an impl
}
}
}

90 changes: 42 additions & 48 deletions src/librustc_typeck/coherence/unsafety.rs
Original file line number Diff line number Diff line change
@@ -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 => {}

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);
}
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);
}

(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);
}
}

112 changes: 56 additions & 56 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
@@ -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,14 +1372,17 @@ fn find_existential_constraints<'a, 'tcx>(
intravisit::walk_trait_item(self, it);
}
}

let mut locator = ConstraintLocator {
def_id,
tcx,
found: None,
};
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;

let sized = SizedByDefault::Yes;
let bounds = compute_bounds(&icx, param_ty, &param.bounds, sized, param.span);
predicates.extend(bounds.predicates(tcx, param_ty));
}
_ => {}
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, &param.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,16 +1852,17 @@ fn explicit_predicates_of<'a, 'tcx>(

&hir::WherePredicate::RegionPredicate(ref region_pred) => {
let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None);
for bound in &region_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)
}
_ => 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 {
9 changes: 3 additions & 6 deletions src/librustc_typeck/constrained_type_params.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
19 changes: 8 additions & 11 deletions src/librustc_typeck/impl_wf_check.rs
Original file line number Diff line number Diff line change
@@ -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();
}
98 changes: 44 additions & 54 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
@@ -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)
}

2 changes: 0 additions & 2 deletions src/librustc_typeck/outlives/mod.rs
Original file line number Diff line number Diff line change
@@ -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();
4 changes: 2 additions & 2 deletions src/librustc_typeck/outlives/test.rs
Original file line number Diff line number Diff line change
@@ -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> {
12 changes: 3 additions & 9 deletions src/librustc_typeck/outlives/utils.rs
Original file line number Diff line number Diff line change
@@ -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:
2 changes: 1 addition & 1 deletion src/librustc_typeck/variance/mod.rs
Original file line number Diff line number Diff line change
@@ -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.