Auto merge of #87201 - GuillaumeGomez:rollup-4loi2q9, r=GuillaumeGomez
Rollup of 7 pull requests Successful merges: - #87107 (Loop over all opaque types instead of looking at just the first one with the same DefId) - #87158 (Suggest full enum variant for local modules) - #87174 (Stabilize `[T; N]::map()`) - #87179 (Mark `const_trait_impl` as active) - #87180 (feat(rustdoc): open sidebar menu when links inside it are focused) - #87188 (Add GUI test for auto-hide-trait-implementations setting) - #87200 (TAIT: Infer all inference variables in opaque type substitutions via InferCx) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
74ef0c3e40
57 changed files with 162 additions and 233 deletions
|
@ -127,13 +127,15 @@ impl<K, V> IntoIterator for VecMap<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> Extend<(K, V)> for VecMap<K, V> {
|
impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
|
||||||
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
|
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
|
||||||
self.0.extend(iter);
|
for (k, v) in iter {
|
||||||
|
self.insert(k, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_one(&mut self, item: (K, V)) {
|
fn extend_one(&mut self, (k, v): (K, V)) {
|
||||||
self.0.extend_one(item);
|
self.insert(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_reserve(&mut self, additional: usize) {
|
fn extend_reserve(&mut self, additional: usize) {
|
||||||
|
|
|
@ -534,7 +534,7 @@ declare_features! (
|
||||||
(active, bindings_after_at, "1.41.0", Some(65490), None),
|
(active, bindings_after_at, "1.41.0", Some(65490), None),
|
||||||
|
|
||||||
/// Allows `impl const Trait for T` syntax.
|
/// Allows `impl const Trait for T` syntax.
|
||||||
(incomplete, const_trait_impl, "1.42.0", Some(67792), None),
|
(active, const_trait_impl, "1.42.0", Some(67792), None),
|
||||||
|
|
||||||
/// Allows `T: ?const Trait` syntax in bounds.
|
/// Allows `T: ?const Trait` syntax in bounds.
|
||||||
(incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
|
(incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
|
||||||
|
|
|
@ -857,7 +857,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)]
|
||||||
pub struct OpaqueTypeKey<'tcx> {
|
pub struct OpaqueTypeKey<'tcx> {
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub substs: SubstsRef<'tcx>,
|
pub substs: SubstsRef<'tcx>,
|
||||||
|
|
|
@ -568,6 +568,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
/// - `substs`, the substs used to instantiate this opaque type
|
/// - `substs`, the substs used to instantiate this opaque type
|
||||||
/// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
|
/// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
|
||||||
/// `opaque_defn.concrete_ty`
|
/// `opaque_defn.concrete_ty`
|
||||||
|
#[instrument(skip(self))]
|
||||||
fn infer_opaque_definition_from_instantiation(
|
fn infer_opaque_definition_from_instantiation(
|
||||||
&self,
|
&self,
|
||||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||||
|
@ -576,11 +577,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
|
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
|
||||||
|
|
||||||
debug!(
|
|
||||||
"infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
|
|
||||||
def_id, instantiated_ty
|
|
||||||
);
|
|
||||||
|
|
||||||
// Use substs to build up a reverse map from regions to their
|
// Use substs to build up a reverse map from regions to their
|
||||||
// identity mappings. This is necessary because of `impl
|
// identity mappings. This is necessary because of `impl
|
||||||
// Trait` lifetimes are computed by replacing existing
|
// Trait` lifetimes are computed by replacing existing
|
||||||
|
@ -588,6 +584,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
// `impl Trait` return type, resulting in the parameters
|
// `impl Trait` return type, resulting in the parameters
|
||||||
// shifting.
|
// shifting.
|
||||||
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
|
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
|
||||||
|
debug!(?id_substs);
|
||||||
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
|
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
|
||||||
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
|
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
|
||||||
|
|
||||||
|
@ -602,7 +599,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
instantiated_ty,
|
instantiated_ty,
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
|
debug!(?definition_ty);
|
||||||
|
|
||||||
definition_ty
|
definition_ty
|
||||||
}
|
}
|
||||||
|
@ -857,7 +854,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||||
self.tcx.mk_generator(def_id, substs, movability)
|
self.tcx.mk_generator(def_id, substs, movability)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Param(..) => {
|
ty::Param(param) => {
|
||||||
// Look it up in the substitution list.
|
// Look it up in the substitution list.
|
||||||
match self.map.get(&ty.into()).map(|k| k.unpack()) {
|
match self.map.get(&ty.into()).map(|k| k.unpack()) {
|
||||||
// Found it in the substitution list; replace with the parameter from the
|
// Found it in the substitution list; replace with the parameter from the
|
||||||
|
@ -865,6 +862,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||||
Some(GenericArgKind::Type(t1)) => t1,
|
Some(GenericArgKind::Type(t1)) => t1,
|
||||||
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
|
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
|
||||||
None => {
|
None => {
|
||||||
|
debug!(?param, ?self.map);
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
|
@ -931,8 +929,8 @@ struct Instantiator<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||||
|
#[instrument(skip(self))]
|
||||||
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
|
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
|
||||||
debug!("instantiate_opaque_types_in_map(value={:?})", value);
|
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
value.fold_with(&mut BottomUpFolder {
|
value.fold_with(&mut BottomUpFolder {
|
||||||
tcx,
|
tcx,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{is_range_literal, Node};
|
use rustc_hir::{is_range_literal, Node};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -201,7 +202,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let sole_field = &variant.fields[0];
|
let sole_field = &variant.fields[0];
|
||||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||||
if self.can_coerce(expr_ty, sole_field_ty) {
|
if self.can_coerce(expr_ty, sole_field_ty) {
|
||||||
let variant_path = self.tcx.def_path_str(variant.def_id);
|
let variant_path =
|
||||||
|
with_no_trimmed_paths(|| self.tcx.def_path_str(variant.def_id));
|
||||||
// FIXME #56861: DRYer prelude filtering
|
// FIXME #56861: DRYer prelude filtering
|
||||||
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
|
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
|
||||||
if let Some((_, path)) = path.split_once("::") {
|
if let Some((_, path)) = path.split_once("::") {
|
||||||
|
|
|
@ -112,11 +112,9 @@ use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType};
|
use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
|
||||||
use rustc_session::config;
|
use rustc_session::config;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
@ -321,117 +319,6 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDe
|
||||||
&*tcx.typeck(def_id).used_trait_imports
|
&*tcx.typeck(def_id).used_trait_imports
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inspects the substs of opaque types, replacing any inference variables
|
|
||||||
/// with proper generic parameter from the identity substs.
|
|
||||||
///
|
|
||||||
/// This is run after we normalize the function signature, to fix any inference
|
|
||||||
/// variables introduced by the projection of associated types. This ensures that
|
|
||||||
/// any opaque types used in the signature continue to refer to generic parameters,
|
|
||||||
/// allowing them to be considered for defining uses in the function body
|
|
||||||
///
|
|
||||||
/// For example, consider this code.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// trait MyTrait {
|
|
||||||
/// type MyItem;
|
|
||||||
/// fn use_it(self) -> Self::MyItem
|
|
||||||
/// }
|
|
||||||
/// impl<T, I> MyTrait for T where T: Iterator<Item = I> {
|
|
||||||
/// type MyItem = impl Iterator<Item = I>;
|
|
||||||
/// fn use_it(self) -> Self::MyItem {
|
|
||||||
/// self
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// When we normalize the signature of `use_it` from the impl block,
|
|
||||||
/// we will normalize `Self::MyItem` to the opaque type `impl Iterator<Item = I>`
|
|
||||||
/// However, this projection result may contain inference variables, due
|
|
||||||
/// to the way that projection works. We didn't have any inference variables
|
|
||||||
/// in the signature to begin with - leaving them in will cause us to incorrectly
|
|
||||||
/// conclude that we don't have a defining use of `MyItem`. By mapping inference
|
|
||||||
/// variables back to the actual generic parameters, we will correctly see that
|
|
||||||
/// we have a defining use of `MyItem`
|
|
||||||
fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: T) -> T
|
|
||||||
where
|
|
||||||
T: TypeFoldable<'tcx>,
|
|
||||||
{
|
|
||||||
struct FixupFolder<'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeFolder<'tcx> for FixupFolder<'tcx> {
|
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
|
||||||
self.tcx
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|
||||||
match *ty.kind() {
|
|
||||||
ty::Opaque(def_id, substs) => {
|
|
||||||
debug!("fixup_opaque_types: found type {:?}", ty);
|
|
||||||
// Here, we replace any inference variables that occur within
|
|
||||||
// the substs of an opaque type. By definition, any type occurring
|
|
||||||
// in the substs has a corresponding generic parameter, which is what
|
|
||||||
// we replace it with.
|
|
||||||
// This replacement is only run on the function signature, so any
|
|
||||||
// inference variables that we come across must be the rust of projection
|
|
||||||
// (there's no other way for a user to get inference variables into
|
|
||||||
// a function signature).
|
|
||||||
if ty.needs_infer() {
|
|
||||||
let new_substs = InternalSubsts::for_item(self.tcx, def_id, |param, _| {
|
|
||||||
let old_param = substs[param.index as usize];
|
|
||||||
match old_param.unpack() {
|
|
||||||
GenericArgKind::Type(old_ty) => {
|
|
||||||
if let ty::Infer(_) = old_ty.kind() {
|
|
||||||
// Replace inference type with a generic parameter
|
|
||||||
self.tcx.mk_param_from_def(param)
|
|
||||||
} else {
|
|
||||||
old_param.fold_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GenericArgKind::Const(old_const) => {
|
|
||||||
if let ty::ConstKind::Infer(_) = old_const.val {
|
|
||||||
// This should never happen - we currently do not support
|
|
||||||
// 'const projections', e.g.:
|
|
||||||
// `impl<T: SomeTrait> MyTrait for T where <T as SomeTrait>::MyConst == 25`
|
|
||||||
// which should be the only way for us to end up with a const inference
|
|
||||||
// variable after projection. If Rust ever gains support for this kind
|
|
||||||
// of projection, this should *probably* be changed to
|
|
||||||
// `self.tcx.mk_param_from_def(param)`
|
|
||||||
bug!(
|
|
||||||
"Found infer const: `{:?}` in opaque type: {:?}",
|
|
||||||
old_const,
|
|
||||||
ty
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
old_param.fold_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GenericArgKind::Lifetime(old_region) => {
|
|
||||||
if let RegionKind::ReVar(_) = old_region {
|
|
||||||
self.tcx.mk_param_from_def(param)
|
|
||||||
} else {
|
|
||||||
old_param.fold_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let new_ty = self.tcx.mk_opaque(def_id, new_substs);
|
|
||||||
debug!("fixup_opaque_types: new type: {:?}", new_ty);
|
|
||||||
new_ty
|
|
||||||
} else {
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => ty.super_fold_with(self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("fixup_opaque_types({:?})", val);
|
|
||||||
val.fold_with(&mut FixupFolder { tcx })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn typeck_const_arg<'tcx>(
|
fn typeck_const_arg<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
(did, param_did): (LocalDefId, DefId),
|
(did, param_did): (LocalDefId, DefId),
|
||||||
|
@ -510,8 +397,6 @@ fn typeck_with_fallback<'tcx>(
|
||||||
fn_sig,
|
fn_sig,
|
||||||
);
|
);
|
||||||
|
|
||||||
let fn_sig = fixup_opaque_types(tcx, fn_sig);
|
|
||||||
|
|
||||||
let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
|
let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
|
||||||
fcx
|
fcx
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -496,6 +496,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
|
|
||||||
debug_assert!(!instantiated_ty.has_escaping_bound_vars());
|
debug_assert!(!instantiated_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap();
|
||||||
|
|
||||||
// Prevent:
|
// Prevent:
|
||||||
// * `fn foo<T>() -> Foo<T>`
|
// * `fn foo<T>() -> Foo<T>`
|
||||||
// * `fn foo<T: Bound + Other>() -> Foo<T>`
|
// * `fn foo<T: Bound + Other>() -> Foo<T>`
|
||||||
|
@ -508,6 +510,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
// fn foo<U>() -> Foo<U> { .. }
|
// fn foo<U>() -> Foo<U> { .. }
|
||||||
// ```
|
// ```
|
||||||
// figures out the concrete type with `U`, but the stored type is with `T`.
|
// figures out the concrete type with `U`, but the stored type is with `T`.
|
||||||
|
|
||||||
|
// FIXME: why are we calling this here? This seems too early, and duplicated.
|
||||||
let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
|
let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
|
||||||
opaque_type_key,
|
opaque_type_key,
|
||||||
instantiated_ty,
|
instantiated_ty,
|
||||||
|
@ -529,33 +533,33 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !opaque_type_key.substs.needs_infer() {
|
if opaque_type_key.substs.needs_infer() {
|
||||||
// We only want to add an entry into `concrete_opaque_types`
|
span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs)
|
||||||
// if we actually found a defining usage of this opaque type.
|
}
|
||||||
// Otherwise, we do nothing - we'll either find a defining usage
|
|
||||||
// in some other location, or we'll end up emitting an error due
|
// We only want to add an entry into `concrete_opaque_types`
|
||||||
// to the lack of defining usage
|
// if we actually found a defining usage of this opaque type.
|
||||||
if !skip_add {
|
// Otherwise, we do nothing - we'll either find a defining usage
|
||||||
let old_concrete_ty = self
|
// in some other location, or we'll end up emitting an error due
|
||||||
.typeck_results
|
// to the lack of defining usage
|
||||||
.concrete_opaque_types
|
if !skip_add {
|
||||||
.insert(opaque_type_key, definition_ty);
|
let old_concrete_ty = self
|
||||||
if let Some(old_concrete_ty) = old_concrete_ty {
|
.typeck_results
|
||||||
if old_concrete_ty != definition_ty {
|
.concrete_opaque_types
|
||||||
span_bug!(
|
.insert(opaque_type_key, definition_ty);
|
||||||
span,
|
if let Some(old_concrete_ty) = old_concrete_ty {
|
||||||
"`visit_opaque_types` tried to write different types for the same \
|
if old_concrete_ty != definition_ty {
|
||||||
|
span_bug!(
|
||||||
|
span,
|
||||||
|
"`visit_opaque_types` tried to write different types for the same \
|
||||||
opaque type: {:?}, {:?}, {:?}, {:?}",
|
opaque type: {:?}, {:?}, {:?}, {:?}",
|
||||||
opaque_type_key.def_id,
|
opaque_type_key.def_id,
|
||||||
definition_ty,
|
definition_ty,
|
||||||
opaque_defn,
|
opaque_defn,
|
||||||
old_concrete_ty,
|
old_concrete_ty,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.tcx().sess.delay_span_bug(span, "`opaque_defn` has inference variables");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,11 +509,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
use rustc_hir::{Expr, ImplItem, Item, TraitItem};
|
use rustc_hir::{Expr, ImplItem, Item, TraitItem};
|
||||||
|
|
||||||
debug!("find_opaque_ty_constraints({:?})", def_id);
|
|
||||||
|
|
||||||
struct ConstraintLocator<'tcx> {
|
struct ConstraintLocator<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -522,13 +521,11 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstraintLocator<'_> {
|
impl ConstraintLocator<'_> {
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn check(&mut self, def_id: LocalDefId) {
|
fn check(&mut self, def_id: LocalDefId) {
|
||||||
// Don't try to check items that cannot possibly constrain the type.
|
// Don't try to check items that cannot possibly constrain the type.
|
||||||
if !self.tcx.has_typeck_results(def_id) {
|
if !self.tcx.has_typeck_results(def_id) {
|
||||||
debug!(
|
debug!("no constraint: no typeck results");
|
||||||
"find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no typeck results",
|
|
||||||
self.def_id, def_id,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Calling `mir_borrowck` can lead to cycle errors through
|
// Calling `mir_borrowck` can lead to cycle errors through
|
||||||
|
@ -540,21 +537,19 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
.get_by(|(key, _)| key.def_id == self.def_id)
|
.get_by(|(key, _)| key.def_id == self.def_id)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
debug!(
|
debug!("no constraints in typeck results");
|
||||||
"find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
|
|
||||||
self.def_id, def_id,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Use borrowck to get the type with unerased regions.
|
// Use borrowck to get the type with unerased regions.
|
||||||
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
|
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
|
||||||
if let Some((opaque_type_key, concrete_type)) =
|
debug!(?concrete_opaque_types);
|
||||||
concrete_opaque_types.iter().find(|(key, _)| key.def_id == self.def_id)
|
for (opaque_type_key, concrete_type) in concrete_opaque_types {
|
||||||
{
|
if opaque_type_key.def_id != self.def_id {
|
||||||
debug!(
|
// Ignore constraints for other opaque types.
|
||||||
"find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
|
continue;
|
||||||
self.def_id, def_id, concrete_type,
|
}
|
||||||
);
|
|
||||||
|
debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
|
||||||
|
|
||||||
// FIXME(oli-obk): trace the actual span from inference to improve errors.
|
// FIXME(oli-obk): trace the actual span from inference to improve errors.
|
||||||
let span = self.tcx.def_span(def_id);
|
let span = self.tcx.def_span(def_id);
|
||||||
|
@ -603,7 +598,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
|
|
||||||
if let Some((prev_span, prev_ty)) = self.found {
|
if let Some((prev_span, prev_ty)) = self.found {
|
||||||
if *concrete_type != prev_ty {
|
if *concrete_type != prev_ty {
|
||||||
debug!("find_opaque_ty_constraints: span={:?}", span);
|
debug!(?span);
|
||||||
// Found different concrete types for the opaque type.
|
// Found different concrete types for the opaque type.
|
||||||
let mut err = self.tcx.sess.struct_span_err(
|
let mut err = self.tcx.sess.struct_span_err(
|
||||||
span,
|
span,
|
||||||
|
@ -619,11 +614,6 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
} else {
|
} else {
|
||||||
self.found = Some((span, concrete_type));
|
self.found = Some((span, concrete_type));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
"find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
|
|
||||||
self.def_id, def_id,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,6 @@ impl<T, const N: usize> [T; N] {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(array_map)]
|
|
||||||
/// let x = [1, 2, 3];
|
/// let x = [1, 2, 3];
|
||||||
/// let y = x.map(|v| v + 1);
|
/// let y = x.map(|v| v + 1);
|
||||||
/// assert_eq!(y, [2, 3, 4]);
|
/// assert_eq!(y, [2, 3, 4]);
|
||||||
|
@ -310,7 +309,7 @@ impl<T, const N: usize> [T; N] {
|
||||||
/// let y = x.map(|v| v.len());
|
/// let y = x.map(|v| v.len());
|
||||||
/// assert_eq!(y, [6, 9, 3, 3]);
|
/// assert_eq!(y, [6, 9, 3, 3]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "array_map", issue = "75243")]
|
#[stable(feature = "array_map", since = "1.55.0")]
|
||||||
pub fn map<F, U>(self, f: F) -> [U; N]
|
pub fn map<F, U>(self, f: F) -> [U; N]
|
||||||
where
|
where
|
||||||
F: FnMut(T) -> U,
|
F: FnMut(T) -> U,
|
||||||
|
@ -377,7 +376,7 @@ impl<T, const N: usize> [T; N] {
|
||||||
/// array if its elements are not `Copy`.
|
/// array if its elements are not `Copy`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(array_methods, array_map)]
|
/// #![feature(array_methods)]
|
||||||
///
|
///
|
||||||
/// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
|
/// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
|
||||||
/// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
|
/// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(alloc_layout_extra)]
|
#![feature(alloc_layout_extra)]
|
||||||
#![feature(array_chunks)]
|
#![feature(array_chunks)]
|
||||||
#![feature(array_methods)]
|
#![feature(array_methods)]
|
||||||
#![feature(array_map)]
|
|
||||||
#![feature(array_windows)]
|
#![feature(array_windows)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
|
@ -1732,7 +1732,8 @@ details.undocumented[open] > summary::before {
|
||||||
width: calc(100% + 30px);
|
width: calc(100% + 30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-it {
|
.show-it, .sidebar-elems:focus-within {
|
||||||
|
z-index: 2;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/test/rustdoc-gui/auto-hide-trait-implementations.goml
Normal file
13
src/test/rustdoc-gui/auto-hide-trait-implementations.goml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Checks that the setting "auto hide trait implementations" is working as expected.
|
||||||
|
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||||
|
|
||||||
|
// By default, the trait implementations are not collapsed.
|
||||||
|
assert-attribute: ("#trait-implementations-list > details", {"open": ""}, ALL)
|
||||||
|
|
||||||
|
// We now set the setting to auto hide all trait implementations.
|
||||||
|
local-storage: {"rustdoc-auto-hide-trait-implementations": "true" }
|
||||||
|
// We reload to ensure the trait implementations are collapsed as expected.
|
||||||
|
reload:
|
||||||
|
|
||||||
|
// We now check that all matching elements don't have the open attributes.
|
||||||
|
assert-attribute-false: ("#trait-implementations-list > details", {"open": ""}, ALL)
|
|
@ -8,3 +8,13 @@ assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
|
||||||
// Opening the sidebar menu.
|
// Opening the sidebar menu.
|
||||||
click: ".sidebar-menu"
|
click: ".sidebar-menu"
|
||||||
assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
|
assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
|
||||||
|
// Closing the sidebar menu.
|
||||||
|
click: ".sidebar-menu"
|
||||||
|
assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
|
||||||
|
// Force the sidebar open by focusing a link inside it.
|
||||||
|
// This makes it easier for keyboard users to get to it.
|
||||||
|
focus: ".sidebar-title"
|
||||||
|
assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
|
||||||
|
// When we tab out of the sidebar, close it.
|
||||||
|
focus: ".search-input"
|
||||||
|
assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#![feature(doc_keyword)]
|
#![feature(doc_keyword)]
|
||||||
#![feature(doc_cfg)]
|
#![feature(doc_cfg)]
|
||||||
|
|
||||||
|
use std::convert::AsRef;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// Basic function with some code examples:
|
/// Basic function with some code examples:
|
||||||
|
@ -36,6 +37,12 @@ impl Foo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for Foo {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
"hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Just a normal enum.
|
/// Just a normal enum.
|
||||||
#[doc(alias = "ThisIsAnAlias")]
|
#[doc(alias = "ThisIsAnAlias")]
|
||||||
pub enum WhoLetTheDogOut {
|
pub enum WhoLetTheDogOut {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#![feature(const_float_bits_conv)]
|
#![feature(const_float_bits_conv)]
|
||||||
#![feature(const_float_classify)]
|
#![feature(const_float_classify)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
// Don't promote
|
// Don't promote
|
||||||
const fn nop<T>(x: T) -> T { x }
|
const fn nop<T>(x: T) -> T { x }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![stable(feature = "foo", since = "1.0.0")]
|
#![stable(feature = "foo", since = "1.0.0")]
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// FIXME: This test should fail since, within a const impl of `Foo`, the bound on `Foo::Bar` should
|
// FIXME: This test should fail since, within a const impl of `Foo`, the bound on `Foo::Bar` should
|
||||||
// require a const impl of `Add` for the associated type.
|
// require a const impl of `Add` for the associated type.
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
struct NonConstAdd(i32);
|
struct NonConstAdd(i32);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
#[default_method_body_is_const] //~ ERROR attribute should be applied
|
#[default_method_body_is_const] //~ ERROR attribute should be applied
|
||||||
trait A {
|
trait A {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: attribute should be applied to a trait method with body
|
error: attribute should be applied to a trait method with body
|
||||||
--> $DIR/attr-misuse.rs:4:1
|
--> $DIR/attr-misuse.rs:3:1
|
||||||
|
|
|
|
||||||
LL | #[default_method_body_is_const]
|
LL | #[default_method_body_is_const]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -13,7 +13,7 @@ LL | | }
|
||||||
| |_- not a trait method or missing a body
|
| |_- not a trait method or missing a body
|
||||||
|
|
||||||
error: attribute should be applied to a trait method with body
|
error: attribute should be applied to a trait method with body
|
||||||
--> $DIR/attr-misuse.rs:13:1
|
--> $DIR/attr-misuse.rs:12:1
|
||||||
|
|
|
|
||||||
LL | #[default_method_body_is_const]
|
LL | #[default_method_body_is_const]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -21,7 +21,7 @@ LL | fn main() {}
|
||||||
| ------------ not a trait method or missing a body
|
| ------------ not a trait method or missing a body
|
||||||
|
|
||||||
error: attribute should be applied to a trait method with body
|
error: attribute should be applied to a trait method with body
|
||||||
--> $DIR/attr-misuse.rs:6:5
|
--> $DIR/attr-misuse.rs:5:5
|
||||||
|
|
|
|
||||||
LL | #[default_method_body_is_const]
|
LL | #[default_method_body_is_const]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
pub trait MyTrait {
|
pub trait MyTrait {
|
||||||
fn func(self);
|
fn func(self);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
pub trait Plus {
|
pub trait Plus {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/call-const-trait-method-fail.rs:25:5
|
--> $DIR/call-const-trait-method-fail.rs:24:5
|
||||||
|
|
|
|
||||||
LL | a.plus(b)
|
LL | a.plus(b)
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
struct Int(i32);
|
struct Int(i32);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_fn_trait_bound)]
|
#![feature(const_fn_trait_bound)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// ignore-test
|
// ignore-test
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_fn_trait_bound)]
|
#![feature(const_fn_trait_bound)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
pub struct Int(i32);
|
pub struct Int(i32);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`
|
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`
|
||||||
--> $DIR/const-and-non-const-impl.rs:6:1
|
--> $DIR/const-and-non-const-impl.rs:5:1
|
||||||
|
|
|
|
||||||
LL | impl const std::ops::Add for i32 {
|
LL | impl const std::ops::Add for i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -8,7 +8,7 @@ LL | impl const std::ops::Add for i32 {
|
||||||
- impl Add for i32;
|
- impl Add for i32;
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`
|
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`
|
||||||
--> $DIR/const-and-non-const-impl.rs:24:1
|
--> $DIR/const-and-non-const-impl.rs:23:1
|
||||||
|
|
|
|
||||||
LL | impl std::ops::Add for Int {
|
LL | impl std::ops::Add for Int {
|
||||||
| -------------------------- first implementation here
|
| -------------------------- first implementation here
|
||||||
|
@ -17,7 +17,7 @@ LL | impl const std::ops::Add for Int {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
|
||||||
|
|
||||||
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||||
--> $DIR/const-and-non-const-impl.rs:6:1
|
--> $DIR/const-and-non-const-impl.rs:5:1
|
||||||
|
|
|
|
||||||
LL | impl const std::ops::Add for i32 {
|
LL | impl const std::ops::Add for i32 {
|
||||||
| ^^^^^^^^^^^-------------^^^^^---
|
| ^^^^^^^^^^^-------------^^^^^---
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/const-check-fns-in-const-impl.rs:12:16
|
--> $DIR/const-check-fns-in-const-impl.rs:11:16
|
||||||
|
|
|
|
||||||
LL | fn foo() { non_const() }
|
LL | fn foo() { non_const() }
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_fn_trait_bound)] // FIXME is this needed?
|
#![feature(const_fn_trait_bound)] // FIXME is this needed?
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
trait ConstDefaultFn: Sized {
|
trait ConstDefaultFn: Sized {
|
||||||
fn b(self);
|
fn b(self);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/const-default-method-bodies.rs:26:5
|
--> $DIR/const-default-method-bodies.rs:25:5
|
||||||
|
|
|
|
||||||
LL | NonConstImpl.a();
|
LL | NonConstImpl.a();
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: expected identifier, found keyword `impl`
|
error: expected identifier, found keyword `impl`
|
||||||
--> $DIR/const-impl-norecover.rs:6:7
|
--> $DIR/const-impl-norecover.rs:5:7
|
||||||
|
|
|
|
||||||
LL | const impl Foo {
|
LL | const impl Foo {
|
||||||
| ^^^^ expected identifier, found keyword
|
| ^^^^ expected identifier, found keyword
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
trait Foo {}
|
trait Foo {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: expected identifier, found keyword `impl`
|
error: expected identifier, found keyword `impl`
|
||||||
--> $DIR/const-impl-recovery.rs:6:7
|
--> $DIR/const-impl-recovery.rs:5:7
|
||||||
|
|
|
|
||||||
LL | const impl Foo for i32 {}
|
LL | const impl Foo for i32 {}
|
||||||
| ^^^^ expected identifier, found keyword
|
| ^^^^ expected identifier, found keyword
|
||||||
|
@ -10,7 +10,7 @@ LL | impl const Foo for i32 {}
|
||||||
|-- ^^^^^
|
|-- ^^^^^
|
||||||
|
|
||||||
error: expected identifier, found keyword `impl`
|
error: expected identifier, found keyword `impl`
|
||||||
--> $DIR/const-impl-recovery.rs:10:7
|
--> $DIR/const-impl-recovery.rs:9:7
|
||||||
|
|
|
|
||||||
LL | const impl<T: Foo> Bar for T {}
|
LL | const impl<T: Foo> Bar for T {}
|
||||||
| ^^^^ expected identifier, found keyword
|
| ^^^^ expected identifier, found keyword
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/cross-crate.rs:16:5
|
--> $DIR/cross-crate.rs:15:5
|
||||||
|
|
|
|
||||||
LL | NonConst.func();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// revisions: stock gated
|
// revisions: stock gated
|
||||||
#![cfg_attr(gated, feature(const_trait_impl))]
|
#![cfg_attr(gated, feature(const_trait_impl))]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
// aux-build: cross-crate.rs
|
// aux-build: cross-crate.rs
|
||||||
extern crate cross_crate;
|
extern crate cross_crate;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/cross-crate.rs:16:5
|
--> $DIR/cross-crate.rs:15:5
|
||||||
|
|
|
|
||||||
LL | NonConst.func();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/cross-crate.rs:18:5
|
--> $DIR/cross-crate.rs:17:5
|
||||||
|
|
|
|
||||||
LL | Const.func();
|
LL | Const.func();
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: fatal error triggered by #[rustc_error]
|
error: fatal error triggered by #[rustc_error]
|
||||||
--> $DIR/feature-gate.rs:14:1
|
--> $DIR/feature-gate.rs:13:1
|
||||||
|
|
|
|
||||||
LL | fn main() {}
|
LL | fn main() {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// gate-test-const_trait_impl
|
// gate-test-const_trait_impl
|
||||||
|
|
||||||
#![cfg_attr(gated, feature(const_trait_impl))]
|
#![cfg_attr(gated, feature(const_trait_impl))]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0658]: const trait impls are experimental
|
error[E0658]: const trait impls are experimental
|
||||||
--> $DIR/feature-gate.rs:10:6
|
--> $DIR/feature-gate.rs:9:6
|
||||||
|
|
|
|
||||||
LL | impl const T for S {}
|
LL | impl const T for S {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_fn_trait_bound)]
|
#![feature(const_fn_trait_bound)]
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Regression test for #69615.
|
// Regression test for #69615.
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
pub trait MyTrait {
|
pub trait MyTrait {
|
||||||
fn method(&self) -> Option<()>;
|
fn method(&self) -> Option<()>;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0744]: `?` is not allowed in a `const fn`
|
error[E0744]: `?` is not allowed in a `const fn`
|
||||||
--> $DIR/hir-const-check.rs:12:9
|
--> $DIR/hir-const-check.rs:11:9
|
||||||
|
|
|
|
||||||
LL | Some(())?;
|
LL | Some(())?;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
trait Tr {
|
trait Tr {
|
||||||
fn req(&self);
|
fn req(&self);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: const trait implementations may not use non-const default functions
|
error: const trait implementations may not use non-const default functions
|
||||||
--> $DIR/impl-with-default-fn.rs:18:1
|
--> $DIR/impl-with-default-fn.rs:17:1
|
||||||
|
|
|
|
||||||
LL | / impl const Tr for S {
|
LL | / impl const Tr for S {
|
||||||
LL | | fn req(&self) {}
|
LL | | fn req(&self) {}
|
||||||
|
@ -9,7 +9,7 @@ LL | | }
|
||||||
= note: `prov` not implemented
|
= note: `prov` not implemented
|
||||||
|
|
||||||
error: const trait implementations may not use non-const default functions
|
error: const trait implementations may not use non-const default functions
|
||||||
--> $DIR/impl-with-default-fn.rs:33:1
|
--> $DIR/impl-with-default-fn.rs:32:1
|
||||||
|
|
|
|
||||||
LL | / impl const Tr for u32 {
|
LL | / impl const Tr for u32 {
|
||||||
LL | | fn req(&self) {}
|
LL | | fn req(&self) {}
|
||||||
|
@ -20,7 +20,7 @@ LL | | }
|
||||||
= note: `prov` not implemented
|
= note: `prov` not implemented
|
||||||
|
|
||||||
error[E0046]: not all trait items implemented, missing: `req`
|
error[E0046]: not all trait items implemented, missing: `req`
|
||||||
--> $DIR/impl-with-default-fn.rs:27:1
|
--> $DIR/impl-with-default-fn.rs:26:1
|
||||||
|
|
|
|
||||||
LL | fn req(&self);
|
LL | fn req(&self);
|
||||||
| -------------- `req` from trait
|
| -------------- `req` from trait
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(allow_internal_unstable)]
|
#![feature(allow_internal_unstable)]
|
||||||
#![feature(const_add)]
|
#![feature(const_add)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: trait methods cannot be stable const fn
|
error: trait methods cannot be stable const fn
|
||||||
--> $DIR/stability.rs:14:5
|
--> $DIR/stability.rs:13:5
|
||||||
|
|
|
|
||||||
LL | / fn sub(self, rhs: Self) -> Self {
|
LL | / fn sub(self, rhs: Self) -> Self {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -8,7 +8,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: `<Int as Add>::add` is not yet stable as a const fn
|
error: `<Int as Add>::add` is not yet stable as a const fn
|
||||||
--> $DIR/stability.rs:32:5
|
--> $DIR/stability.rs:31:5
|
||||||
|
|
|
|
||||||
LL | Int(1i32) + Int(2i32)
|
LL | Int(1i32) + Int(2i32)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#![feature(const_trait_bound_opt_out)]
|
#![feature(const_trait_bound_opt_out)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
// For now, this parses since an error does not occur until AST lowering.
|
// For now, this parses since an error does not occur until AST lowering.
|
||||||
impl ?const T {}
|
impl ?const T {}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
mod option {
|
||||||
|
pub enum O<T> {
|
||||||
|
Some(T),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28
|
||||||
|
|
|
||||||
|
LL | let _: option::O<()> = ();
|
||||||
|
| ------------- ^^
|
||||||
|
| | |
|
||||||
|
| | expected enum `O`, found `()`
|
||||||
|
| | help: try using a variant of the expected enum: `option::O::Some(())`
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected enum `O<()>`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -9,7 +9,7 @@ trait Bug {
|
||||||
impl Bug for &() {
|
impl Bug for &() {
|
||||||
type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
|
type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
|
||||||
//~^ ERROR the trait bound `(): Bug` is not satisfied
|
//~^ ERROR the trait bound `(): Bug` is not satisfied
|
||||||
//~^^ ERROR could not find defining uses
|
//~^^ ERROR the trait bound `(): Bug` is not satisfied
|
||||||
|
|
||||||
const FUN: fn() -> Self::Item = || ();
|
const FUN: fn() -> Self::Item = || ();
|
||||||
//~^ ERROR type alias impl trait is not permitted here
|
//~^ ERROR type alias impl trait is not permitted here
|
||||||
|
|
|
@ -25,11 +25,14 @@ LL | type Item = impl Bug;
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<&() as Bug>
|
<&() as Bug>
|
||||||
|
|
||||||
error: could not find defining uses
|
error[E0277]: the trait bound `(): Bug` is not satisfied
|
||||||
--> $DIR/issue-60371.rs:10:17
|
--> $DIR/issue-60371.rs:10:17
|
||||||
|
|
|
|
||||||
LL | type Item = impl Bug;
|
LL | type Item = impl Bug;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^ the trait `Bug` is not implemented for `()`
|
||||||
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<&() as Bug>
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ trait Output<'a> {}
|
||||||
impl<'a> Output<'a> for &'a str {}
|
impl<'a> Output<'a> for &'a str {}
|
||||||
|
|
||||||
fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
|
fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
|
||||||
|
//~^ ERROR: concrete type differs from previous defining opaque type use
|
||||||
let out: OpaqueOutputImpl<'a> = arg;
|
let out: OpaqueOutputImpl<'a> = arg;
|
||||||
arg
|
arg
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,18 @@ note: hidden type `&'<empty> str` captures lifetime smaller than the function bo
|
||||||
LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
|
LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: concrete type differs from previous defining opaque type use
|
||||||
|
--> $DIR/issue-85113.rs:14:1
|
||||||
|
|
|
||||||
|
LL | fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'<empty> str`, got `&'a str`
|
||||||
|
|
|
||||||
|
note: previous use here
|
||||||
|
--> $DIR/issue-85113.rs:14:1
|
||||||
|
|
|
||||||
|
LL | fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0477]: the type `&'<empty> str` does not fulfill the required lifetime
|
error[E0477]: the type `&'<empty> str` does not fulfill the required lifetime
|
||||||
--> $DIR/issue-85113.rs:5:29
|
--> $DIR/issue-85113.rs:5:29
|
||||||
|
|
|
|
||||||
|
@ -42,7 +54,7 @@ LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
|
||||||
= note: expected `Output<'a>`
|
= note: expected `Output<'a>`
|
||||||
found `Output<'_>`
|
found `Output<'_>`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0477, E0495, E0700.
|
Some errors have detailed explanations: E0477, E0495, E0700.
|
||||||
For more information about an error, try `rustc --explain E0477`.
|
For more information about an error, try `rustc --explain E0477`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue