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:
commit
a74d1862d4
35 changed files with 246 additions and 86 deletions
|
@ -21,7 +21,7 @@ use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
|
|||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
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::middle::cstore::EncodedMetadata;
|
||||
|
@ -465,17 +465,13 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
|
|||
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) {
|
||||
let mut files = vec![];
|
||||
|
||||
if let Some(ref path) = module.object {
|
||||
files.push(path.clone());
|
||||
}
|
||||
let path = module.object.as_ref().map(|path| path.clone());
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -817,7 +813,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
|||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
|
||||
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));
|
||||
object = Some(obj_out.clone());
|
||||
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
|
||||
|
|
|
@ -120,6 +120,7 @@ E0223: include_str!("./error_codes/E0223.md"),
|
|||
E0224: include_str!("./error_codes/E0224.md"),
|
||||
E0225: include_str!("./error_codes/E0225.md"),
|
||||
E0226: include_str!("./error_codes/E0226.md"),
|
||||
E0228: include_str!("./error_codes/E0228.md"),
|
||||
E0229: include_str!("./error_codes/E0229.md"),
|
||||
E0230: include_str!("./error_codes/E0230.md"),
|
||||
E0231: include_str!("./error_codes/E0231.md"),
|
||||
|
@ -482,7 +483,6 @@ E0753: include_str!("./error_codes/E0753.md"),
|
|||
// E0218, // no associated type defined
|
||||
// E0219, // associated type defined in higher-ranked supertrait
|
||||
E0227, // ambiguous lifetime bound, explicit lifetime bound required
|
||||
E0228, // explicit lifetime bound required
|
||||
// E0233,
|
||||
// E0234,
|
||||
// E0235, // structure constructor specifies a structure of type but
|
||||
|
|
40
src/librustc_error_codes/error_codes/E0228.md
Normal file
40
src/librustc_error_codes/error_codes/E0228.md
Normal 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
|
|
@ -1,6 +1,8 @@
|
|||
The value of `N` that was specified for `repr(align(N))` was not a power
|
||||
of two, or was greater than 2^29.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0589
|
||||
#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
|
||||
enum Foo {
|
||||
|
|
|
@ -15,7 +15,7 @@ pub mod assert_module_sources;
|
|||
mod persist;
|
||||
|
||||
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::dep_graph_tcx_init;
|
||||
pub use persist::finalize_session_directory;
|
||||
|
|
|
@ -134,7 +134,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|||
|
||||
for swp in work_products {
|
||||
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);
|
||||
if !path.exists() {
|
||||
all_files_exist = false;
|
||||
|
|
|
@ -21,5 +21,5 @@ pub use load::LoadResult;
|
|||
pub use load::{load_dep_graph, DepGraphFuture};
|
||||
pub use save::save_dep_graph;
|
||||
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;
|
||||
|
|
|
@ -74,9 +74,9 @@ pub fn save_work_product_index(
|
|||
if !new_work_products.contains_key(id) {
|
||||
work_product::delete_workproduct_files(sess, wp);
|
||||
debug_assert!(
|
||||
wp.saved_files
|
||||
.iter()
|
||||
.all(|file_name| { !in_incr_comp_dir_sess(sess, file_name).exists() })
|
||||
wp.saved_file.as_ref().map_or(true, |file_name| {
|
||||
!in_incr_comp_dir_sess(sess, &file_name).exists()
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ pub fn save_work_product_index(
|
|||
debug_assert!({
|
||||
new_work_products
|
||||
.iter()
|
||||
.flat_map(|(_, wp)| wp.saved_files.iter())
|
||||
.flat_map(|(_, wp)| wp.saved_file.iter())
|
||||
.map(|name| in_incr_comp_dir_sess(sess, name))
|
||||
.all(|path| path.exists())
|
||||
});
|
||||
|
|
|
@ -7,43 +7,41 @@ use rustc_session::Session;
|
|||
use std::fs as std_fs;
|
||||
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,
|
||||
cgu_name: &str,
|
||||
files: &[PathBuf],
|
||||
path: &Option<PathBuf>,
|
||||
) -> 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()?;
|
||||
|
||||
let saved_files = files
|
||||
.iter()
|
||||
.map(|path| {
|
||||
let file_name = format!("{}.o", cgu_name);
|
||||
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
|
||||
match link_or_copy(path, &path_in_incr_dir) {
|
||||
Ok(_) => Some(file_name),
|
||||
Err(err) => {
|
||||
sess.warn(&format!(
|
||||
"error copying object file `{}` \
|
||||
to incremental directory as `{}`: {}",
|
||||
path.display(),
|
||||
path_in_incr_dir.display(),
|
||||
err
|
||||
));
|
||||
None
|
||||
}
|
||||
let saved_file = if let Some(path) = path {
|
||||
let file_name = format!("{}.o", cgu_name);
|
||||
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
|
||||
match link_or_copy(path, &path_in_incr_dir) {
|
||||
Ok(_) => Some(file_name),
|
||||
Err(err) => {
|
||||
sess.warn(&format!(
|
||||
"error copying object file `{}` to incremental directory as `{}`: {}",
|
||||
path.display(),
|
||||
path_in_incr_dir.display(),
|
||||
err
|
||||
));
|
||||
return 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);
|
||||
Some((work_product_id, work_product))
|
||||
}
|
||||
|
||||
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);
|
||||
match std_fs::remove_file(&path) {
|
||||
Ok(()) => {}
|
||||
|
|
|
@ -325,8 +325,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("enforce_member_constraint: final least choice = {:?}", least_choice);
|
||||
if least_choice != member_lower_bound {
|
||||
// (#72087) Different `ty::Regions` can be known to be equal, for
|
||||
// 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);
|
||||
true
|
||||
} else {
|
||||
|
@ -578,8 +591,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
self.tcx().mk_region(ReScope(lub))
|
||||
}
|
||||
|
||||
(&ReEarlyBound(_), &ReEarlyBound(_) | &ReFree(_))
|
||||
| (&ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
|
||||
(&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
|
||||
self.region_rels.lub_free_regions(a, b)
|
||||
}
|
||||
|
||||
|
|
|
@ -380,11 +380,27 @@ trait UnusedDelimLint {
|
|||
);
|
||||
|
||||
fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
|
||||
followed_by_block
|
||||
&& match inner.kind {
|
||||
ExprKind::Ret(_) | ExprKind::Break(..) => true,
|
||||
_ => parser::contains_exterior_struct_lit(&inner),
|
||||
// Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
|
||||
let lhs_needs_parens = {
|
||||
let mut innermost = 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(
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ty::subst::SubstsRef;
|
|||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem};
|
||||
use rustc_macros::HashStable;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
|
||||
|
@ -117,11 +118,11 @@ pub struct OverloadedDeref<'tcx> {
|
|||
impl<'tcx> OverloadedDeref<'tcx> {
|
||||
pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
|
||||
let trait_def_id = match self.mutbl {
|
||||
hir::Mutability::Not => tcx.lang_items().deref_trait(),
|
||||
hir::Mutability::Mut => tcx.lang_items().deref_mut_trait(),
|
||||
hir::Mutability::Not => tcx.require_lang_item(DerefTraitLangItem, None),
|
||||
hir::Mutability::Mut => tcx.require_lang_item(DerefMutTraitLangItem, None),
|
||||
};
|
||||
let method_def_id = tcx
|
||||
.associated_items(trait_def_id.unwrap())
|
||||
.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.find(|m| m.kind == ty::AssocKind::Fn)
|
||||
.unwrap()
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
|
|||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir::def::Namespace;
|
||||
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 std::fmt;
|
||||
|
@ -375,7 +375,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
substs: ty::SubstsRef<'tcx>,
|
||||
) -> Instance<'tcx> {
|
||||
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
|
||||
.associated_items(fn_once)
|
||||
.in_definition_order()
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_ast::ast::{self, IntTy, UintTy};
|
|||
use rustc_attr as attr;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
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_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_substs = tcx.intern_substs(&[env_ty.into()]);
|
||||
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
|
||||
|
||||
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_substs = tcx.intern_substs(&[
|
||||
sig.yield_ty.into(),
|
||||
|
|
|
@ -10,6 +10,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::{CoerceUnsizedTraitLangItem, CopyTraitLangItem, SizedTraitLangItem};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
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 {
|
||||
let tcx = self.tcx();
|
||||
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, &[]),
|
||||
};
|
||||
|
||||
|
@ -1468,7 +1469,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.check_rvalue(body, rv, location);
|
||||
if !self.tcx().features().unsized_locals {
|
||||
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, &[]),
|
||||
};
|
||||
self.prove_trait_ref(
|
||||
|
@ -2013,7 +2014,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
ty::Predicate::Trait(
|
||||
ty::Binder::bind(ty::TraitPredicate {
|
||||
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, &[]),
|
||||
),
|
||||
}),
|
||||
|
@ -2037,7 +2041,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
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, &[]),
|
||||
};
|
||||
|
||||
|
@ -2135,7 +2139,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
CastKind::Pointer(PointerCast::Unsize) => {
|
||||
let &ty = ty;
|
||||
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()]),
|
||||
};
|
||||
|
||||
|
|
|
@ -580,10 +580,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||
}
|
||||
mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
|
||||
let tcx = self.tcx;
|
||||
let exchange_malloc_fn_def_id = tcx
|
||||
.lang_items()
|
||||
.require(ExchangeMallocFnLangItem)
|
||||
.unwrap_or_else(|e| tcx.sess.fatal(&e));
|
||||
let exchange_malloc_fn_def_id =
|
||||
tcx.require_lang_item(ExchangeMallocFnLangItem, None);
|
||||
let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
|
||||
if should_monomorphize_locally(tcx, &instance) {
|
||||
self.output.push(create_fn_mono_item(instance));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::FnMutTraitLangItem;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
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)
|
||||
}
|
||||
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
|
||||
.associated_items(fn_mut)
|
||||
.in_definition_order()
|
||||
|
|
|
@ -61,6 +61,7 @@ use crate::util::storage;
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
|
||||
use rustc_index::bit_set::{BitMatrix, BitSet};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
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>) {
|
||||
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 substs = tcx.intern_substs(&[ref_gen_ty.into()]);
|
||||
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>
|
||||
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_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
|
||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::util::patch::MirPatch;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::lang_items::{BoxFreeFnLangItem, DropTraitLangItem};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::traits::Reveal;
|
||||
|
@ -535,7 +535,7 @@ where
|
|||
fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock {
|
||||
debug!("destructor_call_block({:?}, {:?})", self, succ);
|
||||
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 ty = self.place_ty(self.place);
|
||||
let substs = tcx.mk_substs_trait(ty, &[]);
|
||||
|
@ -877,8 +877,7 @@ where
|
|||
) -> BasicBlock {
|
||||
let tcx = self.tcx();
|
||||
let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
|
||||
let free_func =
|
||||
tcx.require_lang_item(lang_items::BoxFreeFnLangItem, Some(self.source_info.span));
|
||||
let free_func = tcx.require_lang_item(BoxFreeFnLangItem, Some(self.source_info.span));
|
||||
let args = adt.variants[VariantIdx::new(0)]
|
||||
.fields
|
||||
.iter()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::EqTraitLangItem;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
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
|
||||
// not *yet* implement `PartialEq`. So for now we leave this here.
|
||||
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(
|
||||
self.tcx(),
|
||||
self.param_env,
|
||||
|
|
|
@ -860,8 +860,8 @@ impl<K: DepKind> DepGraph<K> {
|
|||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct WorkProduct {
|
||||
pub cgu_name: String,
|
||||
/// Saved files associated with this CGU.
|
||||
pub saved_files: Vec<String>,
|
||||
/// Saved file associated with this CGU.
|
||||
pub saved_file: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -283,6 +283,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
.unwrap_or(false);
|
||||
let is_from = format!("{}", trait_ref.print_only_trait_path())
|
||||
.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 {
|
||||
(
|
||||
Some(format!(
|
||||
|
@ -405,6 +407,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
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
|
||||
if !trait_ref.has_infer_types_or_consts()
|
||||
&& 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);
|
||||
self.report_similar_impl_candidates(impl_candidates, &mut err);
|
||||
}
|
||||
self.suggest_change_mut(
|
||||
&obligation,
|
||||
&mut err,
|
||||
&trait_ref,
|
||||
points_at_arg,
|
||||
);
|
||||
// Changing mutability doesn't make a difference to whether we have
|
||||
// an `Unsize` impl (Fixes ICE in #71036)
|
||||
if !is_unsize {
|
||||
self.suggest_change_mut(
|
||||
&obligation,
|
||||
&mut err,
|
||||
&trait_ref,
|
||||
points_at_arg,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If this error is due to `!: Trait` not implemented but `(): Trait` is
|
||||
|
|
|
@ -20,6 +20,7 @@ use crate::traits::error_reporting::InferCtxtExt;
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
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 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(
|
||||
tcx,
|
||||
|
@ -1309,7 +1310,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
|
|||
debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
|
||||
|
||||
// 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(
|
||||
tcx,
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_trait_selection::traits::{self, ObligationCause};
|
|||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::DerefTraitLangItem;
|
||||
use rustc_hir::{is_range_literal, Node};
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
||||
|
@ -634,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ if sp == expr.span && !is_macro => {
|
||||
// Check for `Deref` implementations by constructing a predicate to
|
||||
// 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
|
||||
.tcx
|
||||
.associated_items(deref_trait)
|
||||
|
|
|
@ -737,6 +737,8 @@ pub fn panicking() -> bool {
|
|||
/// The thread may sleep longer than the duration specified due to scheduling
|
||||
/// 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
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
///
|
||||
/// On Unix platforms, the underlying syscall may be interrupted by a
|
||||
|
|
17
src/test/ui/issues/issue-71036.rs
Normal file
17
src/test/ui/issues/issue-71036.rs
Normal 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() {}
|
12
src/test/ui/issues/issue-71036.stderr
Normal file
12
src/test/ui/issues/issue-71036.stderr
Normal 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`.
|
23
src/test/ui/lint/issue-71290-unused-paren-binop.rs
Normal file
23
src/test/ui/lint/issue-71290-unused-paren-binop.rs
Normal 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() {}
|
|
@ -18,3 +18,4 @@ LL | fn f(t: &Ref2<dyn Test>) {
|
|||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0228`.
|
||||
|
|
|
@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0228`.
|
||||
|
|
|
@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0228`.
|
||||
|
|
|
@ -6,3 +6,4 @@ LL | fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() }
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0228`.
|
||||
|
|
7
src/test/ui/regions/issue-72051-member-region-hang.rs
Normal file
7
src/test/ui/regions/issue-72051-member-region-hang.rs
Normal 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() {}
|
|
@ -252,5 +252,5 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell
|
|||
|
||||
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`.
|
||||
|
|
|
@ -18,4 +18,5 @@ LL | x: Box<dyn Debug + '_>,
|
|||
|
||||
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`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue