1
Fork 0

Auto merge of #72202 - Dylan-DPC:rollup-6lbxh1s, r=Dylan-DPC

Rollup of 8 pull requests

Successful merges:

 - #71910 (Fix unused_parens false positive when using binary operations)
 - #72087 (Fix hang in lexical_region_resolve)
 - #72126 (Change `WorkProduct::saved_files` to an `Option`.)
 - #72127 (add long error explanation for E0228)
 - #72141 (Warn against thread::sleep in async fn)
 - #72170 (use `require_lang_item` over `unwrap`.)
 - #72191 (Clean up E0589 explanation)
 - #72194 (Don't ICE on missing `Unsize` impl)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-05-14 19:35:24 +00:00
commit a74d1862d4
35 changed files with 246 additions and 86 deletions

View file

@ -21,7 +21,7 @@ use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
use rustc_fs_util::link_or_copy; use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_incremental::{ use rustc_incremental::{
copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
}; };
use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::cstore::EncodedMetadata;
@ -465,17 +465,13 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
return work_products; return work_products;
} }
let _timer = sess.timer("incr_comp_copy_cgu_workproducts"); let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
let mut files = vec![]; let path = module.object.as_ref().map(|path| path.clone());
if let Some(ref path) = module.object {
files.push(path.clone());
}
if let Some((id, product)) = if let Some((id, product)) =
copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, &path)
{ {
work_products.insert(id, product); work_products.insert(id, product);
} }
@ -817,7 +813,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
) -> Result<WorkItemResult<B>, FatalError> { ) -> Result<WorkItemResult<B>, FatalError> {
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
let mut object = None; let mut object = None;
for saved_file in &module.source.saved_files { if let Some(saved_file) = module.source.saved_file {
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
object = Some(obj_out.clone()); object = Some(obj_out.clone());
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file); let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file);

View file

@ -120,6 +120,7 @@ E0223: include_str!("./error_codes/E0223.md"),
E0224: include_str!("./error_codes/E0224.md"), E0224: include_str!("./error_codes/E0224.md"),
E0225: include_str!("./error_codes/E0225.md"), E0225: include_str!("./error_codes/E0225.md"),
E0226: include_str!("./error_codes/E0226.md"), E0226: include_str!("./error_codes/E0226.md"),
E0228: include_str!("./error_codes/E0228.md"),
E0229: include_str!("./error_codes/E0229.md"), E0229: include_str!("./error_codes/E0229.md"),
E0230: include_str!("./error_codes/E0230.md"), E0230: include_str!("./error_codes/E0230.md"),
E0231: include_str!("./error_codes/E0231.md"), E0231: include_str!("./error_codes/E0231.md"),
@ -482,7 +483,6 @@ E0753: include_str!("./error_codes/E0753.md"),
// E0218, // no associated type defined // E0218, // no associated type defined
// E0219, // associated type defined in higher-ranked supertrait // E0219, // associated type defined in higher-ranked supertrait
E0227, // ambiguous lifetime bound, explicit lifetime bound required E0227, // ambiguous lifetime bound, explicit lifetime bound required
E0228, // explicit lifetime bound required
// E0233, // E0233,
// E0234, // E0234,
// E0235, // structure constructor specifies a structure of type but // E0235, // structure constructor specifies a structure of type but

View file

@ -0,0 +1,40 @@
The lifetime bound for this object type cannot be deduced from context and must
be specified.
Erroneous code example:
```compile_fail,E0228
trait Trait { }
struct TwoBounds<'a, 'b, T: Sized + 'a + 'b> {
x: &'a i32,
y: &'b i32,
z: T,
}
type Foo<'a, 'b> = TwoBounds<'a, 'b, dyn Trait>;
```
When a trait object is used as a type argument of a generic type, Rust will try
to infer its lifetime if unspecified. However, this isn't possible when the
containing type has more than one lifetime bound.
The above example can be resolved by either reducing the number of lifetime
bounds to one or by making the trait object lifetime explicit, like so:
```
trait Trait { }
struct TwoBounds<'a, 'b, T: Sized + 'a + 'b> {
x: &'a i32,
y: &'b i32,
z: T,
}
type Foo<'a, 'b> = TwoBounds<'a, 'b, dyn Trait + 'b>;
```
For more information, see [RFC 599] and its amendment [RFC 1156].
[RFC 599]: https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md
[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md

View file

@ -1,6 +1,8 @@
The value of `N` that was specified for `repr(align(N))` was not a power The value of `N` that was specified for `repr(align(N))` was not a power
of two, or was greater than 2^29. of two, or was greater than 2^29.
Erroneous code example:
```compile_fail,E0589 ```compile_fail,E0589
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two #[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
enum Foo { enum Foo {

View file

@ -15,7 +15,7 @@ pub mod assert_module_sources;
mod persist; mod persist;
pub use assert_dep_graph::assert_dep_graph; pub use assert_dep_graph::assert_dep_graph;
pub use persist::copy_cgu_workproducts_to_incr_comp_cache_dir; pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir;
pub use persist::delete_workproduct_files; pub use persist::delete_workproduct_files;
pub use persist::dep_graph_tcx_init; pub use persist::dep_graph_tcx_init;
pub use persist::finalize_session_directory; pub use persist::finalize_session_directory;

View file

@ -134,7 +134,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
for swp in work_products { for swp in work_products {
let mut all_files_exist = true; let mut all_files_exist = true;
for file_name in swp.work_product.saved_files.iter() { if let Some(ref file_name) = swp.work_product.saved_file {
let path = in_incr_comp_dir_sess(sess, file_name); let path = in_incr_comp_dir_sess(sess, file_name);
if !path.exists() { if !path.exists() {
all_files_exist = false; all_files_exist = false;

View file

@ -21,5 +21,5 @@ pub use load::LoadResult;
pub use load::{load_dep_graph, DepGraphFuture}; pub use load::{load_dep_graph, DepGraphFuture};
pub use save::save_dep_graph; pub use save::save_dep_graph;
pub use save::save_work_product_index; pub use save::save_work_product_index;
pub use work_product::copy_cgu_workproducts_to_incr_comp_cache_dir; pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
pub use work_product::delete_workproduct_files; pub use work_product::delete_workproduct_files;

View file

@ -74,9 +74,9 @@ pub fn save_work_product_index(
if !new_work_products.contains_key(id) { if !new_work_products.contains_key(id) {
work_product::delete_workproduct_files(sess, wp); work_product::delete_workproduct_files(sess, wp);
debug_assert!( debug_assert!(
wp.saved_files wp.saved_file.as_ref().map_or(true, |file_name| {
.iter() !in_incr_comp_dir_sess(sess, &file_name).exists()
.all(|file_name| { !in_incr_comp_dir_sess(sess, file_name).exists() }) })
); );
} }
} }
@ -85,7 +85,7 @@ pub fn save_work_product_index(
debug_assert!({ debug_assert!({
new_work_products new_work_products
.iter() .iter()
.flat_map(|(_, wp)| wp.saved_files.iter()) .flat_map(|(_, wp)| wp.saved_file.iter())
.map(|name| in_incr_comp_dir_sess(sess, name)) .map(|name| in_incr_comp_dir_sess(sess, name))
.all(|path| path.exists()) .all(|path| path.exists())
}); });

View file

@ -7,43 +7,41 @@ use rustc_session::Session;
use std::fs as std_fs; use std::fs as std_fs;
use std::path::PathBuf; use std::path::PathBuf;
pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
sess: &Session, sess: &Session,
cgu_name: &str, cgu_name: &str,
files: &[PathBuf], path: &Option<PathBuf>,
) -> Option<(WorkProductId, WorkProduct)> { ) -> Option<(WorkProductId, WorkProduct)> {
debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files); debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path);
sess.opts.incremental.as_ref()?; sess.opts.incremental.as_ref()?;
let saved_files = files let saved_file = if let Some(path) = path {
.iter() let file_name = format!("{}.o", cgu_name);
.map(|path| { let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
let file_name = format!("{}.o", cgu_name); match link_or_copy(path, &path_in_incr_dir) {
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); Ok(_) => Some(file_name),
match link_or_copy(path, &path_in_incr_dir) { Err(err) => {
Ok(_) => Some(file_name), sess.warn(&format!(
Err(err) => { "error copying object file `{}` to incremental directory as `{}`: {}",
sess.warn(&format!( path.display(),
"error copying object file `{}` \ path_in_incr_dir.display(),
to incremental directory as `{}`: {}", err
path.display(), ));
path_in_incr_dir.display(), return None;
err
));
None
}
} }
}) }
.collect::<Option<Vec<_>>>()?; } else {
None
};
let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files }; let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file };
let work_product_id = WorkProductId::from_cgu_name(cgu_name); let work_product_id = WorkProductId::from_cgu_name(cgu_name);
Some((work_product_id, work_product)) Some((work_product_id, work_product))
} }
pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
for file_name in &work_product.saved_files { if let Some(ref file_name) = work_product.saved_file {
let path = in_incr_comp_dir_sess(sess, file_name); let path = in_incr_comp_dir_sess(sess, file_name);
match std_fs::remove_file(&path) { match std_fs::remove_file(&path) {
Ok(()) => {} Ok(()) => {}

View file

@ -325,8 +325,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
} }
debug!("enforce_member_constraint: final least choice = {:?}", least_choice); // (#72087) Different `ty::Regions` can be known to be equal, for
if least_choice != member_lower_bound { // example, we know that `'a` and `'static` are equal in a function
// with a parameter of type `&'static &'a ()`.
//
// When we have two equal regions like this `expansion` will use
// `lub_concrete_regions` to pick a canonical representative. The same
// choice is needed here so that we don't end up in a cycle of
// `expansion` changing the region one way and the code here changing
// it back.
let lub = self.lub_concrete_regions(least_choice, member_lower_bound);
debug!(
"enforce_member_constraint: final least choice = {:?}\nlub = {:?}",
least_choice, lub
);
if lub != member_lower_bound {
*var_values.value_mut(member_vid) = VarValue::Value(least_choice); *var_values.value_mut(member_vid) = VarValue::Value(least_choice);
true true
} else { } else {
@ -578,8 +591,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.tcx().mk_region(ReScope(lub)) self.tcx().mk_region(ReScope(lub))
} }
(&ReEarlyBound(_), &ReEarlyBound(_) | &ReFree(_)) (&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
| (&ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
self.region_rels.lub_free_regions(a, b) self.region_rels.lub_free_regions(a, b)
} }

View file

@ -380,11 +380,27 @@ trait UnusedDelimLint {
); );
fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
followed_by_block // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
&& match inner.kind { let lhs_needs_parens = {
ExprKind::Ret(_) | ExprKind::Break(..) => true, let mut innermost = inner;
_ => parser::contains_exterior_struct_lit(&inner), loop {
if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind {
innermost = lhs;
if !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(innermost) {
break true;
}
} else {
break false;
}
} }
};
lhs_needs_parens
|| (followed_by_block
&& match inner.kind {
ExprKind::Ret(_) | ExprKind::Break(..) => true,
_ => parser::contains_exterior_struct_lit(&inner),
})
} }
fn emit_unused_delims_expr( fn emit_unused_delims_expr(

View file

@ -2,6 +2,7 @@ use crate::ty::subst::SubstsRef;
use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem};
use rustc_macros::HashStable; use rustc_macros::HashStable;
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
@ -117,11 +118,11 @@ pub struct OverloadedDeref<'tcx> {
impl<'tcx> OverloadedDeref<'tcx> { impl<'tcx> OverloadedDeref<'tcx> {
pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
let trait_def_id = match self.mutbl { let trait_def_id = match self.mutbl {
hir::Mutability::Not => tcx.lang_items().deref_trait(), hir::Mutability::Not => tcx.require_lang_item(DerefTraitLangItem, None),
hir::Mutability::Mut => tcx.lang_items().deref_mut_trait(), hir::Mutability::Mut => tcx.require_lang_item(DerefMutTraitLangItem, None),
}; };
let method_def_id = tcx let method_def_id = tcx
.associated_items(trait_def_id.unwrap()) .associated_items(trait_def_id)
.in_definition_order() .in_definition_order()
.find(|m| m.kind == ty::AssocKind::Fn) .find(|m| m.kind == ty::AssocKind::Fn)
.unwrap() .unwrap()

View file

@ -4,7 +4,7 @@ use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::DropInPlaceFnLangItem; use rustc_hir::lang_items::{DropInPlaceFnLangItem, FnOnceTraitLangItem};
use rustc_macros::HashStable; use rustc_macros::HashStable;
use std::fmt; use std::fmt;
@ -375,7 +375,7 @@ impl<'tcx> Instance<'tcx> {
substs: ty::SubstsRef<'tcx>, substs: ty::SubstsRef<'tcx>,
) -> Instance<'tcx> { ) -> Instance<'tcx> {
debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs);
let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let fn_once = tcx.require_lang_item(FnOnceTraitLangItem, None);
let call_once = tcx let call_once = tcx
.associated_items(fn_once) .associated_items(fn_once)
.in_definition_order() .in_definition_order()

View file

@ -8,6 +8,7 @@ use rustc_ast::ast::{self, IntTy, UintTy};
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
@ -2314,13 +2315,13 @@ impl<'tcx> ty::Instance<'tcx> {
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
let pin_did = tcx.lang_items().pin_type().unwrap(); let pin_did = tcx.require_lang_item(PinTypeLangItem, None);
let pin_adt_ref = tcx.adt_def(pin_did); let pin_adt_ref = tcx.adt_def(pin_did);
let pin_substs = tcx.intern_substs(&[env_ty.into()]); let pin_substs = tcx.intern_substs(&[env_ty.into()]);
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
sig.map_bound(|sig| { sig.map_bound(|sig| {
let state_did = tcx.lang_items().gen_state().unwrap(); let state_did = tcx.require_lang_item(GeneratorStateLangItem, None);
let state_adt_ref = tcx.adt_def(state_did); let state_adt_ref = tcx.adt_def(state_did);
let state_substs = tcx.intern_substs(&[ let state_substs = tcx.intern_substs(&[
sig.yield_ty.into(), sig.yield_ty.into(),

View file

@ -10,6 +10,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{CoerceUnsizedTraitLangItem, CopyTraitLangItem, SizedTraitLangItem};
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::env::RegionBoundPairs;
@ -502,7 +503,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
let tcx = self.tcx(); let tcx = self.tcx();
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().copy_trait().unwrap(), def_id: tcx.require_lang_item(CopyTraitLangItem, Some(self.last_span)),
substs: tcx.mk_substs_trait(place_ty.ty, &[]), substs: tcx.mk_substs_trait(place_ty.ty, &[]),
}; };
@ -1468,7 +1469,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_rvalue(body, rv, location); self.check_rvalue(body, rv, location);
if !self.tcx().features().unsized_locals { if !self.tcx().features().unsized_locals {
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().sized_trait().unwrap(), def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)),
substs: tcx.mk_substs_trait(place_ty, &[]), substs: tcx.mk_substs_trait(place_ty, &[]),
}; };
self.prove_trait_ref( self.prove_trait_ref(
@ -2013,7 +2014,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ty::Predicate::Trait( ty::Predicate::Trait(
ty::Binder::bind(ty::TraitPredicate { ty::Binder::bind(ty::TraitPredicate {
trait_ref: ty::TraitRef::new( trait_ref: ty::TraitRef::new(
self.tcx().lang_items().copy_trait().unwrap(), self.tcx().require_lang_item(
CopyTraitLangItem,
Some(self.last_span),
),
tcx.mk_substs_trait(ty, &[]), tcx.mk_substs_trait(ty, &[]),
), ),
}), }),
@ -2037,7 +2041,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().sized_trait().unwrap(), def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)),
substs: tcx.mk_substs_trait(ty, &[]), substs: tcx.mk_substs_trait(ty, &[]),
}; };
@ -2135,7 +2139,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
CastKind::Pointer(PointerCast::Unsize) => { CastKind::Pointer(PointerCast::Unsize) => {
let &ty = ty; let &ty = ty;
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), def_id: tcx.require_lang_item(
CoerceUnsizedTraitLangItem,
Some(self.last_span),
),
substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]),
}; };

View file

@ -580,10 +580,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
} }
mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => { mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
let tcx = self.tcx; let tcx = self.tcx;
let exchange_malloc_fn_def_id = tcx let exchange_malloc_fn_def_id =
.lang_items() tcx.require_lang_item(ExchangeMallocFnLangItem, None);
.require(ExchangeMallocFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e));
let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
if should_monomorphize_locally(tcx, &instance) { if should_monomorphize_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(instance)); self.output.push(create_fn_mono_item(instance));

View file

@ -1,5 +1,6 @@
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::FnMutTraitLangItem;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::subst::{InternalSubsts, Subst};
@ -70,7 +71,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None) build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None)
} }
ty::InstanceDef::ClosureOnceShim { call_once: _ } => { ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); let fn_mut = tcx.require_lang_item(FnMutTraitLangItem, None);
let call_mut = tcx let call_mut = tcx
.associated_items(fn_mut) .associated_items(fn_mut)
.in_definition_order() .in_definition_order()

View file

@ -61,6 +61,7 @@ use crate::util::storage;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::bit_set::{BitMatrix, BitSet};
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
@ -381,7 +382,7 @@ fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo
fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let ref_gen_ty = body.local_decls.raw[1].ty; let ref_gen_ty = body.local_decls.raw[1].ty;
let pin_did = tcx.lang_items().pin_type().unwrap(); let pin_did = tcx.require_lang_item(PinTypeLangItem, Some(body.span));
let pin_adt_ref = tcx.adt_def(pin_did); let pin_adt_ref = tcx.adt_def(pin_did);
let substs = tcx.intern_substs(&[ref_gen_ty.into()]); let substs = tcx.intern_substs(&[ref_gen_ty.into()]);
let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs);
@ -1207,7 +1208,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
}; };
// Compute GeneratorState<yield_ty, return_ty> // Compute GeneratorState<yield_ty, return_ty>
let state_did = tcx.lang_items().gen_state().unwrap(); let state_did = tcx.require_lang_item(GeneratorStateLangItem, None);
let state_adt_ref = tcx.adt_def(state_did); let state_adt_ref = tcx.adt_def(state_did);
let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]); let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);

View file

@ -1,6 +1,6 @@
use crate::util::patch::MirPatch; use crate::util::patch::MirPatch;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items; use rustc_hir::lang_items::{BoxFreeFnLangItem, DropTraitLangItem};
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::traits::Reveal; use rustc_middle::traits::Reveal;
@ -535,7 +535,7 @@ where
fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock { fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock {
debug!("destructor_call_block({:?}, {:?})", self, succ); debug!("destructor_call_block({:?}, {:?})", self, succ);
let tcx = self.tcx(); let tcx = self.tcx();
let drop_trait = tcx.lang_items().drop_trait().unwrap(); let drop_trait = tcx.require_lang_item(DropTraitLangItem, None);
let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap(); let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap();
let ty = self.place_ty(self.place); let ty = self.place_ty(self.place);
let substs = tcx.mk_substs_trait(ty, &[]); let substs = tcx.mk_substs_trait(ty, &[]);
@ -877,8 +877,7 @@ where
) -> BasicBlock { ) -> BasicBlock {
let tcx = self.tcx(); let tcx = self.tcx();
let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
let free_func = let free_func = tcx.require_lang_item(BoxFreeFnLangItem, Some(self.source_info.span));
tcx.require_lang_item(lang_items::BoxFreeFnLangItem, Some(self.source_info.span));
let args = adt.variants[VariantIdx::new(0)] let args = adt.variants[VariantIdx::new(0)]
.fields .fields
.iter() .iter()

View file

@ -1,4 +1,5 @@
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items::EqTraitLangItem;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::Field; use rustc_middle::mir::Field;
@ -140,7 +141,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
// code at the moment, because types like `for <'a> fn(&'a ())` do // code at the moment, because types like `for <'a> fn(&'a ())` do
// not *yet* implement `PartialEq`. So for now we leave this here. // not *yet* implement `PartialEq`. So for now we leave this here.
let ty_is_partial_eq: bool = { let ty_is_partial_eq: bool = {
let partial_eq_trait_id = self.tcx().lang_items().eq_trait().unwrap(); let partial_eq_trait_id = self.tcx().require_lang_item(EqTraitLangItem, None);
let obligation: PredicateObligation<'_> = predicate_for_trait_def( let obligation: PredicateObligation<'_> = predicate_for_trait_def(
self.tcx(), self.tcx(),
self.param_env, self.param_env,

View file

@ -860,8 +860,8 @@ impl<K: DepKind> DepGraph<K> {
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct WorkProduct { pub struct WorkProduct {
pub cgu_name: String, pub cgu_name: String,
/// Saved files associated with this CGU. /// Saved file associated with this CGU.
pub saved_files: Vec<String>, pub saved_file: Option<String>,
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -283,6 +283,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
.unwrap_or(false); .unwrap_or(false);
let is_from = format!("{}", trait_ref.print_only_trait_path()) let is_from = format!("{}", trait_ref.print_only_trait_path())
.starts_with("std::convert::From<"); .starts_with("std::convert::From<");
let is_unsize =
{ Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() };
let (message, note) = if is_try && is_from { let (message, note) = if is_try && is_from {
( (
Some(format!( Some(format!(
@ -405,6 +407,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return; return;
} }
if is_unsize {
// If the obligation failed due to a missing implementation of the
// `Unsize` trait, give a pointer to why that might be the case
err.note(
"all implementations of `Unsize` are provided \
automatically by the compiler, see \
<https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \
for more information",
);
}
// Try to report a help message // Try to report a help message
if !trait_ref.has_infer_types_or_consts() if !trait_ref.has_infer_types_or_consts()
&& self.predicate_can_apply(obligation.param_env, trait_ref) && self.predicate_can_apply(obligation.param_env, trait_ref)
@ -427,12 +440,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let impl_candidates = self.find_similar_impl_candidates(trait_ref); let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err); self.report_similar_impl_candidates(impl_candidates, &mut err);
} }
self.suggest_change_mut( // Changing mutability doesn't make a difference to whether we have
&obligation, // an `Unsize` impl (Fixes ICE in #71036)
&mut err, if !is_unsize {
&trait_ref, self.suggest_change_mut(
points_at_arg, &obligation,
); &mut err,
&trait_ref,
points_at_arg,
);
}
} }
// If this error is due to `!: Trait` not implemented but `(): Trait` is // If this error is due to `!: Trait` not implemented but `(): Trait` is

View file

@ -20,6 +20,7 @@ use crate::traits::error_reporting::InferCtxtExt;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
@ -1222,7 +1223,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
let tcx = selcx.tcx(); let tcx = selcx.tcx();
let gen_def_id = tcx.lang_items().gen_trait().unwrap(); let gen_def_id = tcx.require_lang_item(GeneratorTraitLangItem, None);
let predicate = super::util::generator_trait_ref_and_outputs( let predicate = super::util::generator_trait_ref_and_outputs(
tcx, tcx,
@ -1309,7 +1310,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig); debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
// the `Output` associated type is declared on `FnOnce` // the `Output` associated type is declared on `FnOnce`
let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); let fn_once_def_id = tcx.require_lang_item(FnOnceTraitLangItem, None);
let predicate = super::util::closure_trait_ref_and_return_type( let predicate = super::util::closure_trait_ref_and_return_type(
tcx, tcx,

View file

@ -7,6 +7,7 @@ use rustc_trait_selection::traits::{self, ObligationCause};
use rustc_ast::util::parser::PREC_POSTFIX; use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items::DerefTraitLangItem;
use rustc_hir::{is_range_literal, Node}; use rustc_hir::{is_range_literal, Node};
use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
@ -634,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ if sp == expr.span && !is_macro => { _ if sp == expr.span && !is_macro => {
// Check for `Deref` implementations by constructing a predicate to // Check for `Deref` implementations by constructing a predicate to
// prove: `<T as Deref>::Output == U` // prove: `<T as Deref>::Output == U`
let deref_trait = self.tcx.lang_items().deref_trait().unwrap(); let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(expr.span));
let item_def_id = self let item_def_id = self
.tcx .tcx
.associated_items(deref_trait) .associated_items(deref_trait)

View file

@ -737,6 +737,8 @@ pub fn panicking() -> bool {
/// The thread may sleep longer than the duration specified due to scheduling /// The thread may sleep longer than the duration specified due to scheduling
/// specifics or platform-dependent functionality. It will never sleep less. /// specifics or platform-dependent functionality. It will never sleep less.
/// ///
/// This function is blocking, and should not be used in `async` functions.
///
/// # Platform-specific behavior /// # Platform-specific behavior
/// ///
/// On Unix platforms, the underlying syscall may be interrupted by a /// On Unix platforms, the underlying syscall may be interrupted by a
@ -763,6 +765,8 @@ pub fn sleep_ms(ms: u32) {
/// The thread may sleep longer than the duration specified due to scheduling /// The thread may sleep longer than the duration specified due to scheduling
/// specifics or platform-dependent functionality. It will never sleep less. /// specifics or platform-dependent functionality. It will never sleep less.
/// ///
/// This function is blocking, and should not be used in `async` functions.
///
/// # Platform-specific behavior /// # Platform-specific behavior
/// ///
/// On Unix platforms, the underlying syscall may be interrupted by a /// On Unix platforms, the underlying syscall may be interrupted by a

View file

@ -0,0 +1,17 @@
#![feature(unsize, dispatch_from_dyn)]
use std::marker::Unsize;
use std::ops::DispatchFromDyn;
#[allow(unused)]
struct Foo<'a, T: ?Sized> {
_inner: &'a &'a T,
}
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
//~^ ERROR the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
//~| NOTE the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
//~| NOTE required because of the requirements on the impl
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0277]: the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
--> $DIR/issue-71036.rs:11:1
|
LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
|
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
= note: required because of the requirements on the impl of `std::ops::DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,23 @@
// check-pass
// Make sure unused parens lint doesn't emit a false positive.
// See https://github.com/rust-lang/rust/issues/71290 for details.
#![deny(unused_parens)]
fn x() -> u8 {
({ 0 }) + 1
}
fn y() -> u8 {
({ 0 } + 1)
}
pub fn foo(a: bool, b: bool) -> u8 {
(if a { 1 } else { 0 } + if b { 1 } else { 0 })
}
pub fn bar() -> u8 {
// Make sure nested expressions are handled correctly as well
({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)
}
fn main() {}

View file

@ -18,3 +18,4 @@ LL | fn f(t: &Ref2<dyn Test>) {
error: aborting due to 3 previous errors error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0228`.

View file

@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0228`.

View file

@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0228`.

View file

@ -6,3 +6,4 @@ LL | fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() }
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0228`.

View file

@ -0,0 +1,7 @@
// Regression test for #72051, hang when resolving regions.
// check-pass
// edition:2018
pub async fn query<'a>(_: &(), _: &(), _: (&(dyn std::any::Any + 'a),) ) {}
fn main() {}

View file

@ -252,5 +252,5 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell
error: aborting due to 28 previous errors error: aborting due to 28 previous errors
Some errors have detailed explanations: E0106, E0107. Some errors have detailed explanations: E0106, E0107, E0228.
For more information about an error, try `rustc --explain E0106`. For more information about an error, try `rustc --explain E0106`.

View file

@ -18,4 +18,5 @@ LL | x: Box<dyn Debug + '_>,
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0106`. Some errors have detailed explanations: E0106, E0228.
For more information about an error, try `rustc --explain E0106`.