Auto merge of #96428 - GuillaumeGomez:rollup-4noqr33, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #94022 (Clarify that `Cow::into_owned` returns owned data) - #94703 (Fix codegen bug in "ptx-kernel" abi related to arg passing) - #95949 (Implement Default for AssertUnwindSafe) - #96361 (Switch JS code to ES6) - #96372 (Suggest calling method on nested field when struct is missing method) - #96386 (simplify `describe_field` func in borrowck's diagnostics part) - #96400 (Correct documentation for `Rvalue::ShallowInitBox`) - #96415 (Remove references to git.io) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
082e4ca497
21 changed files with 721 additions and 284 deletions
|
|
@ -40,6 +40,7 @@ crate use outlives_suggestion::OutlivesSuggestionBuilder;
|
||||||
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
||||||
crate use region_name::{RegionName, RegionNameSource};
|
crate use region_name::{RegionName, RegionNameSource};
|
||||||
crate use rustc_const_eval::util::CallKind;
|
crate use rustc_const_eval::util::CallKind;
|
||||||
|
use rustc_middle::mir::tcx::PlaceTy;
|
||||||
|
|
||||||
pub(super) struct IncludingDowncast(pub(super) bool);
|
pub(super) struct IncludingDowncast(pub(super) bool);
|
||||||
|
|
||||||
|
|
@ -329,30 +330,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
|
|
||||||
/// End-user visible description of the `field`nth field of `base`
|
/// End-user visible description of the `field`nth field of `base`
|
||||||
fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
|
fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
|
||||||
// FIXME Place2 Make this work iteratively
|
let place_ty = match place {
|
||||||
match place {
|
PlaceRef { local, projection: [] } => PlaceTy::from_ty(self.body.local_decls[local].ty),
|
||||||
PlaceRef { local, projection: [] } => {
|
|
||||||
let local = &self.body.local_decls[local];
|
|
||||||
self.describe_field_from_ty(local.ty, field, None)
|
|
||||||
}
|
|
||||||
PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
|
PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref
|
||||||
self.describe_field(PlaceRef { local, projection: proj_base }, field)
|
| ProjectionElem::Index(..)
|
||||||
}
|
|
||||||
ProjectionElem::Downcast(_, variant_index) => {
|
|
||||||
let base_ty = place.ty(self.body, self.infcx.tcx).ty;
|
|
||||||
self.describe_field_from_ty(base_ty, field, Some(*variant_index))
|
|
||||||
}
|
|
||||||
ProjectionElem::Field(_, field_type) => {
|
|
||||||
self.describe_field_from_ty(*field_type, field, None)
|
|
||||||
}
|
|
||||||
ProjectionElem::Index(..)
|
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. } => {
|
| ProjectionElem::Subslice { .. } => {
|
||||||
self.describe_field(PlaceRef { local, projection: proj_base }, field)
|
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
|
||||||
}
|
}
|
||||||
|
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
|
||||||
|
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
self.describe_field_from_ty(place_ty.ty, field, place_ty.variant_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// End-user visible description of the `field_index`nth field of `ty`
|
/// End-user visible description of the `field_index`nth field of `ty`
|
||||||
|
|
|
||||||
|
|
@ -2581,8 +2581,6 @@ pub enum Rvalue<'tcx> {
|
||||||
/// This is different from a normal transmute because dataflow analysis will treat the box as
|
/// This is different from a normal transmute because dataflow analysis will treat the box as
|
||||||
/// initialized but its content as uninitialized. Like other pointer casts, this in general
|
/// initialized but its content as uninitialized. Like other pointer casts, this in general
|
||||||
/// affects alias analysis.
|
/// affects alias analysis.
|
||||||
///
|
|
||||||
/// Disallowed after drop elaboration.
|
|
||||||
ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
|
ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2592,6 +2592,22 @@ where
|
||||||
|
|
||||||
pointee_info
|
pointee_info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_adt(this: TyAndLayout<'tcx>) -> bool {
|
||||||
|
matches!(this.ty.kind(), ty::Adt(..))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_never(this: TyAndLayout<'tcx>) -> bool {
|
||||||
|
this.ty.kind() == &ty::Never
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_tuple(this: TyAndLayout<'tcx>) -> bool {
|
||||||
|
matches!(this.ty.kind(), ty::Tuple(..))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
|
||||||
|
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ty::Instance<'tcx> {
|
impl<'tcx> ty::Instance<'tcx> {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ impl<T> List<T> {
|
||||||
static EMPTY_SLICE: InOrder<usize, MaxAlign> = InOrder(0, MaxAlign);
|
static EMPTY_SLICE: InOrder<usize, MaxAlign> = InOrder(0, MaxAlign);
|
||||||
unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
|
unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.len
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy> List<T> {
|
impl<T: Copy> List<T> {
|
||||||
|
|
|
||||||
|
|
@ -696,7 +696,13 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
||||||
"sparc" => sparc::compute_abi_info(cx, self),
|
"sparc" => sparc::compute_abi_info(cx, self),
|
||||||
"sparc64" => sparc64::compute_abi_info(cx, self),
|
"sparc64" => sparc64::compute_abi_info(cx, self),
|
||||||
"nvptx" => nvptx::compute_abi_info(self),
|
"nvptx" => nvptx::compute_abi_info(self),
|
||||||
"nvptx64" => nvptx64::compute_abi_info(self),
|
"nvptx64" => {
|
||||||
|
if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel {
|
||||||
|
nvptx64::compute_ptx_kernel_abi_info(cx, self)
|
||||||
|
} else {
|
||||||
|
nvptx64::compute_abi_info(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
"hexagon" => hexagon::compute_abi_info(self),
|
"hexagon" => hexagon::compute_abi_info(self),
|
||||||
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
|
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
|
||||||
"wasm32" | "wasm64" => {
|
"wasm32" | "wasm64" => {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,35 @@
|
||||||
// Reference: PTX Writer's Guide to Interoperability
|
use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform};
|
||||||
// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, FnAbi};
|
|
||||||
|
|
||||||
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
|
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
|
||||||
if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
|
if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
|
||||||
ret.make_indirect();
|
ret.make_indirect();
|
||||||
} else {
|
|
||||||
ret.extend_integer_width_to(64);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
|
fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
|
||||||
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
|
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
|
||||||
arg.make_indirect();
|
arg.make_indirect();
|
||||||
} else {
|
}
|
||||||
arg.extend_integer_width_to(64);
|
}
|
||||||
|
|
||||||
|
fn classify_arg_kernel<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
|
C: HasDataLayout,
|
||||||
|
{
|
||||||
|
if matches!(arg.mode, PassMode::Pair(..)) && (arg.layout.is_adt() || arg.layout.is_tuple()) {
|
||||||
|
let align_bytes = arg.layout.align.abi.bytes();
|
||||||
|
|
||||||
|
let unit = match align_bytes {
|
||||||
|
1 => Reg::i8(),
|
||||||
|
2 => Reg::i16(),
|
||||||
|
4 => Reg::i32(),
|
||||||
|
8 => Reg::i64(),
|
||||||
|
16 => Reg::i128(),
|
||||||
|
_ => unreachable!("Align is given as power of 2 no larger than 16 bytes"),
|
||||||
|
};
|
||||||
|
arg.cast_to(Uniform { unit, total: Size::from_bytes(2 * align_bytes) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,3 +45,20 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
|
||||||
classify_arg(arg);
|
classify_arg(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compute_ptx_kernel_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
|
C: HasDataLayout,
|
||||||
|
{
|
||||||
|
if !fn_abi.ret.layout.is_unit() && !fn_abi.ret.layout.is_never() {
|
||||||
|
panic!("Kernels should not return anything other than () or !");
|
||||||
|
}
|
||||||
|
|
||||||
|
for arg in &mut fn_abi.args {
|
||||||
|
if arg.is_ignore() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
classify_arg_kernel(cx, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1355,6 +1355,10 @@ pub trait TyAbiInterface<'a, C>: Sized {
|
||||||
cx: &C,
|
cx: &C,
|
||||||
offset: Size,
|
offset: Size,
|
||||||
) -> Option<PointeeInfo>;
|
) -> Option<PointeeInfo>;
|
||||||
|
fn is_adt(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
|
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
|
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
|
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
|
|
@ -1396,6 +1400,34 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_adt<C>(self) -> bool
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
{
|
||||||
|
Ty::is_adt(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_never<C>(self) -> bool
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
{
|
||||||
|
Ty::is_never(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_tuple<C>(self) -> bool
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
{
|
||||||
|
Ty::is_tuple(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unit<C>(self) -> bool
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
{
|
||||||
|
Ty::is_unit(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ impl MipsInlineAsmRegClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The reserved registers are somewhat taken from <https://git.io/JUR1k#L150>.
|
// The reserved registers are somewhat taken from
|
||||||
|
// <https://github.com/llvm/llvm-project/blob/deb8f8bcf31540c657716ea5242183b0792702a1/llvm/lib/Target/Mips/MipsRegisterInfo.cpp#L150>.
|
||||||
def_regs! {
|
def_regs! {
|
||||||
Mips MipsInlineAsmReg MipsInlineAsmRegClass {
|
Mips MipsInlineAsmReg MipsInlineAsmRegClass {
|
||||||
r2: reg = ["$2"],
|
r2: reg = ["$2"],
|
||||||
|
|
|
||||||
|
|
@ -2285,14 +2285,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// try to add a suggestion in case the field is a nested field of a field of the Adt
|
// try to add a suggestion in case the field is a nested field of a field of the Adt
|
||||||
if let Some((fields, substs)) = self.get_field_candidates(span, expr_t) {
|
if let Some((fields, substs)) = self.get_field_candidates(span, expr_t) {
|
||||||
for candidate_field in fields.iter() {
|
for candidate_field in fields.iter() {
|
||||||
if let Some(field_path) = self.check_for_nested_field(
|
if let Some(mut field_path) = self.check_for_nested_field_satisfying(
|
||||||
span,
|
span,
|
||||||
field,
|
&|candidate_field, _| candidate_field.ident(self.tcx()) == field,
|
||||||
candidate_field,
|
candidate_field,
|
||||||
substs,
|
substs,
|
||||||
vec![],
|
vec![],
|
||||||
self.tcx.parent_module(id).to_def_id(),
|
self.tcx.parent_module(id).to_def_id(),
|
||||||
) {
|
) {
|
||||||
|
// field_path includes `field` that we're looking for, so pop it.
|
||||||
|
field_path.pop();
|
||||||
|
|
||||||
let field_path_str = field_path
|
let field_path_str = field_path
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| id.name.to_ident_string())
|
.map(|id| id.name.to_ident_string())
|
||||||
|
|
@ -2312,7 +2315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_candidates(
|
crate fn get_field_candidates(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
base_t: Ty<'tcx>,
|
base_t: Ty<'tcx>,
|
||||||
|
|
@ -2337,49 +2340,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
/// This method is called after we have encountered a missing field error to recursively
|
/// This method is called after we have encountered a missing field error to recursively
|
||||||
/// search for the field
|
/// search for the field
|
||||||
fn check_for_nested_field(
|
crate fn check_for_nested_field_satisfying(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
target_field: Ident,
|
matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
|
||||||
candidate_field: &ty::FieldDef,
|
candidate_field: &ty::FieldDef,
|
||||||
subst: SubstsRef<'tcx>,
|
subst: SubstsRef<'tcx>,
|
||||||
mut field_path: Vec<Ident>,
|
mut field_path: Vec<Ident>,
|
||||||
id: DefId,
|
id: DefId,
|
||||||
) -> Option<Vec<Ident>> {
|
) -> Option<Vec<Ident>> {
|
||||||
debug!(
|
debug!(
|
||||||
"check_for_nested_field(span: {:?}, candidate_field: {:?}, field_path: {:?}",
|
"check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
|
||||||
span, candidate_field, field_path
|
span, candidate_field, field_path
|
||||||
);
|
);
|
||||||
|
|
||||||
if candidate_field.ident(self.tcx) == target_field {
|
if field_path.len() > 3 {
|
||||||
Some(field_path)
|
|
||||||
} else if field_path.len() > 3 {
|
|
||||||
// For compile-time reasons and to avoid infinite recursion we only check for fields
|
// For compile-time reasons and to avoid infinite recursion we only check for fields
|
||||||
// up to a depth of three
|
// up to a depth of three
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// recursively search fields of `candidate_field` if it's a ty::Adt
|
// recursively search fields of `candidate_field` if it's a ty::Adt
|
||||||
|
|
||||||
field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
|
field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
|
||||||
let field_ty = candidate_field.ty(self.tcx, subst);
|
let field_ty = candidate_field.ty(self.tcx, subst);
|
||||||
if let Some((nested_fields, subst)) = self.get_field_candidates(span, field_ty) {
|
if let Some((nested_fields, subst)) = self.get_field_candidates(span, field_ty) {
|
||||||
for field in nested_fields.iter() {
|
for field in nested_fields.iter() {
|
||||||
let accessible = field.vis.is_accessible_from(id, self.tcx);
|
if field.vis.is_accessible_from(id, self.tcx) {
|
||||||
if accessible {
|
if matches(candidate_field, field_ty) {
|
||||||
let ident = field.ident(self.tcx).normalize_to_macros_2_0();
|
|
||||||
if ident == target_field {
|
|
||||||
return Some(field_path);
|
return Some(field_path);
|
||||||
}
|
} else if let Some(field_path) = self.check_for_nested_field_satisfying(
|
||||||
let field_path = field_path.clone();
|
|
||||||
if let Some(path) = self.check_for_nested_field(
|
|
||||||
span,
|
span,
|
||||||
target_field,
|
matches,
|
||||||
field,
|
field,
|
||||||
subst,
|
subst,
|
||||||
field_path,
|
field_path.clone(),
|
||||||
id,
|
id,
|
||||||
) {
|
) {
|
||||||
return Some(path);
|
return Some(field_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ use rustc_trait_selection::traits::{
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use super::probe::Mode;
|
use super::probe::{Mode, ProbeScope};
|
||||||
use super::{CandidateSource, MethodError, NoMatchData};
|
use super::{CandidateSource, MethodError, NoMatchData};
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
@ -1129,6 +1129,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
label_span_not_found();
|
label_span_not_found();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let SelfSource::MethodCall(expr) = source
|
||||||
|
&& let Some((fields, substs)) = self.get_field_candidates(span, actual)
|
||||||
|
{
|
||||||
|
let call_expr =
|
||||||
|
self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
|
||||||
|
for candidate_field in fields.iter() {
|
||||||
|
if let Some(field_path) = self.check_for_nested_field_satisfying(
|
||||||
|
span,
|
||||||
|
&|_, field_ty| {
|
||||||
|
self.lookup_probe(
|
||||||
|
span,
|
||||||
|
item_name,
|
||||||
|
field_ty,
|
||||||
|
call_expr,
|
||||||
|
ProbeScope::AllTraits,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
},
|
||||||
|
candidate_field,
|
||||||
|
substs,
|
||||||
|
vec![],
|
||||||
|
self.tcx.parent_module(expr.hir_id).to_def_id(),
|
||||||
|
) {
|
||||||
|
let field_path_str = field_path
|
||||||
|
.iter()
|
||||||
|
.map(|id| id.name.to_ident_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(".");
|
||||||
|
debug!("field_path_str: {:?}", field_path_str);
|
||||||
|
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
item_name.span.shrink_to_lo(),
|
||||||
|
"one of the expressions' fields has a method of the same name",
|
||||||
|
format!("{field_path_str}."),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bound_spans.sort();
|
bound_spans.sort();
|
||||||
bound_spans.dedup();
|
bound_spans.dedup();
|
||||||
for (span, msg) in bound_spans.into_iter() {
|
for (span, msg) in bound_spans.into_iter() {
|
||||||
|
|
|
||||||
|
|
@ -292,8 +292,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data
|
/// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data:
|
||||||
/// and becomes a `Cow::Owned`:
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::borrow::Cow;
|
/// use std::borrow::Cow;
|
||||||
|
|
@ -307,7 +306,8 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Calling `into_owned` on a `Cow::Owned` is a no-op:
|
/// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the
|
||||||
|
/// `Cow` without being cloned.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::borrow::Cow;
|
/// use std::borrow::Cow;
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,13 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "assertunwindsafe_default", since = "1.62.0")]
|
||||||
|
impl<T: Default> Default for AssertUnwindSafe<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||||
impl<F: Future> Future for AssertUnwindSafe<F> {
|
impl<F: Future> Future for AssertUnwindSafe<F> {
|
||||||
type Output = F::Output;
|
type Output = F::Output;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ cfg_if::cfg_if! {
|
||||||
// Android with api less than 21 define sig* functions inline, so it is not
|
// Android with api less than 21 define sig* functions inline, so it is not
|
||||||
// available for dynamic link. Implementing sigemptyset and sigaddset allow us
|
// available for dynamic link. Implementing sigemptyset and sigaddset allow us
|
||||||
// to support older Android version (independent of libc version).
|
// to support older Android version (independent of libc version).
|
||||||
// The following implementations are based on https://git.io/vSkNf
|
// The following implementations are based on
|
||||||
|
// https://github.com/aosp-mirror/platform_bionic/blob/ad8dcd6023294b646e5a8288c0ed431b0845da49/libc/include/android/legacy_signal_inlines.h
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_os = "android")] {
|
if #[cfg(target_os = "android")] {
|
||||||
pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
|
pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,7 @@
|
||||||
// Local js definitions:
|
// Local js definitions:
|
||||||
|
/* eslint-env es6 */
|
||||||
|
/* eslint no-var: "error" */
|
||||||
|
/* eslint prefer-const: "error" */
|
||||||
/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
|
/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
|
||||||
/* global addClass, removeClass */
|
/* global addClass, removeClass */
|
||||||
|
|
||||||
|
|
@ -55,9 +58,9 @@
|
||||||
function setEvents() {
|
function setEvents() {
|
||||||
updateLightAndDark();
|
updateLightAndDark();
|
||||||
onEachLazy(document.getElementsByClassName("slider"), function(elem) {
|
onEachLazy(document.getElementsByClassName("slider"), function(elem) {
|
||||||
var toggle = elem.previousElementSibling;
|
const toggle = elem.previousElementSibling;
|
||||||
var settingId = toggle.id;
|
const settingId = toggle.id;
|
||||||
var settingValue = getSettingValue(settingId);
|
const settingValue = getSettingValue(settingId);
|
||||||
if (settingValue !== null) {
|
if (settingValue !== null) {
|
||||||
toggle.checked = settingValue === "true";
|
toggle.checked = settingValue === "true";
|
||||||
}
|
}
|
||||||
|
|
@ -68,9 +71,9 @@
|
||||||
toggle.onkeyrelease = handleKey;
|
toggle.onkeyrelease = handleKey;
|
||||||
});
|
});
|
||||||
onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
|
onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
|
||||||
var select = elem.getElementsByTagName("select")[0];
|
const select = elem.getElementsByTagName("select")[0];
|
||||||
var settingId = select.id;
|
const settingId = select.id;
|
||||||
var settingValue = getSettingValue(settingId);
|
const settingValue = getSettingValue(settingId);
|
||||||
if (settingValue !== null) {
|
if (settingValue !== null) {
|
||||||
select.value = settingValue;
|
select.value = settingValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
254
src/test/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
Normal file
254
src/test/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
// assembly-output: ptx-linker
|
||||||
|
// compile-flags: --crate-type cdylib -C target-cpu=sm_86
|
||||||
|
// only-nvptx64
|
||||||
|
// ignore-nvptx64
|
||||||
|
|
||||||
|
// The following ABI tests are made with nvcc 11.6 does.
|
||||||
|
//
|
||||||
|
// The PTX ABI stability is tied to major versions of the PTX ISA
|
||||||
|
// These tests assume major version 7
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The following correspondence between types are assumed:
|
||||||
|
// u<N> - uint<N>_t
|
||||||
|
// i<N> - int<N>_t
|
||||||
|
// [T, N] - std::array<T, N>
|
||||||
|
// &T - T const*
|
||||||
|
// &mut T - T*
|
||||||
|
|
||||||
|
// CHECK: .version 7
|
||||||
|
|
||||||
|
#![feature(abi_ptx, lang_items, no_core)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct SingleU8 {
|
||||||
|
f: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DoubleU8 {
|
||||||
|
f: u8,
|
||||||
|
g: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleU8 {
|
||||||
|
f: u8,
|
||||||
|
g: u8,
|
||||||
|
h: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleU16 {
|
||||||
|
f: u16,
|
||||||
|
g: u16,
|
||||||
|
h: u16,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleU32 {
|
||||||
|
f: u32,
|
||||||
|
g: u32,
|
||||||
|
h: u32,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleU64 {
|
||||||
|
f: u64,
|
||||||
|
g: u64,
|
||||||
|
h: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DoubleFloat {
|
||||||
|
f: f32,
|
||||||
|
g: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleFloat {
|
||||||
|
f: f32,
|
||||||
|
g: f32,
|
||||||
|
h: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TripleDouble {
|
||||||
|
f: f64,
|
||||||
|
g: f64,
|
||||||
|
h: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ManyIntegers {
|
||||||
|
f: u8,
|
||||||
|
g: u16,
|
||||||
|
h: u32,
|
||||||
|
i: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ManyNumerics {
|
||||||
|
f: u8,
|
||||||
|
g: u16,
|
||||||
|
h: u32,
|
||||||
|
i: u64,
|
||||||
|
j: f32,
|
||||||
|
k: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u8_arg(
|
||||||
|
// CHECK: .param .u8 f_u8_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u8_arg(_a: u8) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u16_arg(
|
||||||
|
// CHECK: .param .u16 f_u16_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u16_arg(_a: u16) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u32_arg(
|
||||||
|
// CHECK: .param .u32 f_u32_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u32_arg(_a: u32) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u64_arg(
|
||||||
|
// CHECK: .param .u64 f_u64_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u64_arg(_a: u64) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u128_arg(
|
||||||
|
// CHECK: .param .align 16 .b8 f_u128_arg_param_0[16]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u128_arg(_a: u128) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_i8_arg(
|
||||||
|
// CHECK: .param .u8 f_i8_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_i8_arg(_a: i8) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_i16_arg(
|
||||||
|
// CHECK: .param .u16 f_i16_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_i16_arg(_a: i16) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_i32_arg(
|
||||||
|
// CHECK: .param .u32 f_i32_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_i32_arg(_a: i32) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_i64_arg(
|
||||||
|
// CHECK: .param .u64 f_i64_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_i64_arg(_a: i64) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_i128_arg(
|
||||||
|
// CHECK: .param .align 16 .b8 f_i128_arg_param_0[16]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_i128_arg(_a: i128) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_f32_arg(
|
||||||
|
// CHECK: .param .f32 f_f32_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_f32_arg(_a: f32) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_f64_arg(
|
||||||
|
// CHECK: .param .f64 f_f64_arg_param_0
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_f64_arg(_a: f64) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_single_u8_arg(
|
||||||
|
// CHECK: .param .align 1 .b8 f_single_u8_arg_param_0[1]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_single_u8_arg(_a: SingleU8) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_double_u8_arg(
|
||||||
|
// CHECK: .param .align 1 .b8 f_double_u8_arg_param_0[2]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_double_u8_arg(_a: DoubleU8) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_u8_arg(
|
||||||
|
// CHECK: .param .align 1 .b8 f_triple_u8_arg_param_0[3]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_u8_arg(_a: TripleU8) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_u16_arg(
|
||||||
|
// CHECK: .param .align 2 .b8 f_triple_u16_arg_param_0[6]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_u16_arg(_a: TripleU16) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_u32_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_triple_u32_arg_param_0[12]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_u32_arg(_a: TripleU32) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_u64_arg(
|
||||||
|
// CHECK: .param .align 8 .b8 f_triple_u64_arg_param_0[24]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_u64_arg(_a: TripleU64) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_many_integers_arg(
|
||||||
|
// CHECK: .param .align 8 .b8 f_many_integers_arg_param_0[16]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_many_integers_arg(_a: ManyIntegers) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_double_float_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_double_float_arg_param_0[8]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_double_float_arg(_a: DoubleFloat) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_float_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_triple_float_arg_param_0[12]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_float_arg(_a: TripleFloat) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_triple_double_arg(
|
||||||
|
// CHECK: .param .align 8 .b8 f_triple_double_arg_param_0[24]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_triple_double_arg(_a: TripleDouble) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_many_numerics_arg(
|
||||||
|
// CHECK: .param .align 8 .b8 f_many_numerics_arg_param_0[32]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_many_numerics_arg(_a: ManyNumerics) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_byte_array_arg(
|
||||||
|
// CHECK: .param .align 1 .b8 f_byte_array_arg_param_0[5]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_byte_array_arg(_a: [u8; 5]) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_float_array_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_float_array_arg_param_0[20]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_float_array_arg(_a: [f32; 5]) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u128_array_arg(
|
||||||
|
// CHECK: .param .align 16 .b8 f_u128_array_arg_param_0[80]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u128_array_arg(_a: [u128; 5]) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_u32_slice_arg(
|
||||||
|
// CHECK: .param .u64 f_u32_slice_arg_param_0
|
||||||
|
// CHECK: .param .u64 f_u32_slice_arg_param_1
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_u32_slice_arg(_a: &[u32]) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_tuple_u8_u8_arg(
|
||||||
|
// CHECK: .param .align 1 .b8 f_tuple_u8_u8_arg_param_0[2]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_arg(_a: (u8, u8)) {}
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_tuple_u32_u32_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_tuple_u32_u32_arg_param_0[8]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_tuple_u32_u32_arg(_a: (u32, u32)) {}
|
||||||
|
|
||||||
|
|
||||||
|
// CHECK: .visible .entry f_tuple_u8_u8_u32_arg(
|
||||||
|
// CHECK: .param .align 4 .b8 f_tuple_u8_u8_u32_arg_param_0[8]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_u32_arg(_a: (u8, u8, u32)) {}
|
||||||
|
|
@ -18,6 +18,10 @@ note: the following trait bounds were not satisfied:
|
||||||
|
|
|
|
||||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||||
|
help: one of the expressions' fields has a method of the same name
|
||||||
|
|
|
||||||
|
LL | let filter = map.stream.filterx(|x: &_| true);
|
||||||
|
| +++++++
|
||||||
|
|
||||||
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
|
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
|
||||||
--> $DIR/issue-30786.rs:140:24
|
--> $DIR/issue-30786.rs:140:24
|
||||||
|
|
@ -39,6 +43,10 @@ note: the following trait bounds were not satisfied:
|
||||||
|
|
|
|
||||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||||
|
help: one of the expressions' fields has a method of the same name
|
||||||
|
|
|
||||||
|
LL | let count = filter.stream.countx();
|
||||||
|
| +++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ note: the following trait bounds were not satisfied:
|
||||||
|
|
|
|
||||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||||
|
help: one of the expressions' fields has a method of the same name
|
||||||
|
|
|
||||||
|
LL | let filter = map.stream.filterx(|x: &_| true);
|
||||||
|
| +++++++
|
||||||
|
|
||||||
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
|
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
|
||||||
--> $DIR/issue-30786.rs:140:24
|
--> $DIR/issue-30786.rs:140:24
|
||||||
|
|
@ -39,6 +43,10 @@ note: the following trait bounds were not satisfied:
|
||||||
|
|
|
|
||||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||||
|
help: one of the expressions' fields has a method of the same name
|
||||||
|
|
|
||||||
|
LL | let count = filter.stream.countx();
|
||||||
|
| +++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
23
src/test/ui/suggestions/field-has-method.rs
Normal file
23
src/test/ui/suggestions/field-has-method.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
struct Kind;
|
||||||
|
|
||||||
|
struct Ty {
|
||||||
|
kind: Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
fn kind(&self) -> Kind {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InferOk<T> {
|
||||||
|
value: T,
|
||||||
|
predicates: Vec<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(i: InferOk<Ty>) {
|
||||||
|
let k = i.kind();
|
||||||
|
//~^ no method named `kind` found for struct `InferOk` in the current scope
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
17
src/test/ui/suggestions/field-has-method.stderr
Normal file
17
src/test/ui/suggestions/field-has-method.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
error[E0599]: no method named `kind` found for struct `InferOk` in the current scope
|
||||||
|
--> $DIR/field-has-method.rs:19:15
|
||||||
|
|
|
||||||
|
LL | struct InferOk<T> {
|
||||||
|
| ----------------- method `kind` not found for this
|
||||||
|
...
|
||||||
|
LL | let k = i.kind();
|
||||||
|
| ^^^^ method not found in `InferOk<Ty>`
|
||||||
|
|
|
||||||
|
help: one of the expressions' fields has a method of the same name
|
||||||
|
|
|
||||||
|
LL | let k = i.value.kind();
|
||||||
|
| ++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
||||||
|
|
@ -85,8 +85,11 @@ function extractFunction(content, functionName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stupid function extractor for array.
|
// Stupid function extractor for array.
|
||||||
function extractArrayVariable(content, arrayName) {
|
function extractArrayVariable(content, arrayName, kind) {
|
||||||
var splitter = "var " + arrayName;
|
if (typeof kind === "undefined") {
|
||||||
|
kind = "let ";
|
||||||
|
}
|
||||||
|
var splitter = kind + arrayName;
|
||||||
while (true) {
|
while (true) {
|
||||||
var start = content.indexOf(splitter);
|
var start = content.indexOf(splitter);
|
||||||
if (start === -1) {
|
if (start === -1) {
|
||||||
|
|
@ -126,12 +129,18 @@ function extractArrayVariable(content, arrayName) {
|
||||||
}
|
}
|
||||||
content = content.slice(start + 1);
|
content = content.slice(start + 1);
|
||||||
}
|
}
|
||||||
|
if (kind === "let ") {
|
||||||
|
return extractArrayVariable(content, arrayName, "const ");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stupid function extractor for variable.
|
// Stupid function extractor for variable.
|
||||||
function extractVariable(content, varName) {
|
function extractVariable(content, varName, kind) {
|
||||||
var splitter = "var " + varName;
|
if (typeof kind === "undefined") {
|
||||||
|
kind = "let ";
|
||||||
|
}
|
||||||
|
var splitter = kind + varName;
|
||||||
while (true) {
|
while (true) {
|
||||||
var start = content.indexOf(splitter);
|
var start = content.indexOf(splitter);
|
||||||
if (start === -1) {
|
if (start === -1) {
|
||||||
|
|
@ -162,6 +171,9 @@ function extractVariable(content, varName) {
|
||||||
}
|
}
|
||||||
content = content.slice(start + 1);
|
content = content.slice(start + 1);
|
||||||
}
|
}
|
||||||
|
if (kind === "let ") {
|
||||||
|
return extractVariable(content, varName, "const ");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue