diff --git a/source/compiler/qsc_frontend/src/compile/tests/multiple_packages.rs b/source/compiler/qsc_frontend/src/compile/tests/multiple_packages.rs index b180007b6d..434dbc7615 100644 --- a/source/compiler/qsc_frontend/src/compile/tests/multiple_packages.rs +++ b/source/compiler/qsc_frontend/src/compile/tests/multiple_packages.rs @@ -496,8 +496,8 @@ fn reexports_still_type_check() { "Bool", "Int", Span { - lo: 128, - hi: 140, + lo: 137, + hi: 139, }, ), ), diff --git a/source/compiler/qsc_frontend/src/typeck/infer.rs b/source/compiler/qsc_frontend/src/typeck/infer.rs index 60ab80413c..a7bfb75604 100644 --- a/source/compiler/qsc_frontend/src/typeck/infer.rs +++ b/source/compiler/qsc_frontend/src/typeck/infer.rs @@ -308,69 +308,67 @@ impl TySource { #[derive(Clone, Debug)] pub(super) enum ArgTy { /// A missing argument, indicating partial application. - Hole(Ty), + Hole(Ty, Span), /// A given argument. - Given(Ty), + Given(Ty, Span), /// A list of arguments. This corresponds literally to tuple syntax, not to any expression of a tuple type. - Tuple(Vec), + Tuple(Vec, Span), } impl ArgTy { /// Applies a function `f` to each type in the argument type. fn map(self, f: &mut impl FnMut(Ty) -> Ty) -> Self { match self { - Self::Hole(ty) => Self::Hole(f(ty)), - Self::Given(ty) => Self::Given(f(ty)), - Self::Tuple(items) => Self::Tuple(items.into_iter().map(|i| i.map(f)).collect()), + Self::Hole(ty, span) => Self::Hole(f(ty), span), + Self::Given(ty, span) => Self::Given(f(ty), span), + Self::Tuple(items, span) => { + Self::Tuple(items.into_iter().map(|i| i.map(f)).collect(), span) + } } } /// Applies the argument type to a parameter type, generating constraints and errors. - fn apply(&self, param: &Ty, span: Span) -> App { + fn apply(&self, param: &Ty) -> App { match (self, param) { // If `arg` is a hole, then it doesn't matter what the param is, // because the hole can be anything. // However, we do know that the type of Arg must be Eq to the type of Param, so we // add that to the constraints. // Preserve the hole. - (Self::Hole(arg), _) => App { + (Self::Hole(arg, arg_span), _) => App { holes: vec![param.clone()], constraints: vec![Constraint::Eq { expected: param.clone(), actual: arg.clone(), - span, + span: *arg_span, }], errors: Vec::new(), }, - // If `arg` is a hole, then it doesn't matter what the param is, - // because the hole can be anything. - // However, we do know that the type of Arg must be Eq to the type of Param, so we - // add that to the constraints. - (Self::Given(arg), _) => App { + (Self::Given(arg, arg_span), _) => App { holes: Vec::new(), constraints: vec![Constraint::Eq { expected: param.clone(), actual: arg.clone(), - span, + span: *arg_span, }], errors: Vec::new(), }, // if both the arg and the param are tuples, then we must check // the types of each element in the tuple and generate iterative applications. - (Self::Tuple(args), Ty::Tuple(params)) => { + (Self::Tuple(args, tuple_span), Ty::Tuple(params)) => { let mut errors = Vec::new(); if args.len() != params.len() { errors.push(Error(ErrorKind::TyMismatch( Ty::Tuple(params.clone()).display(), self.to_ty().display(), - span, + *tuple_span, ))); } let mut holes = Vec::new(); let mut constraints = Vec::new(); for (arg, param) in args.iter().zip(params) { - let mut app = arg.apply(param, span); + let mut app = arg.apply(param); constraints.append(&mut app.constraints); errors.append(&mut app.errors); if app.holes.len() > 1 { @@ -387,22 +385,22 @@ impl ArgTy { } } - (Self::Tuple(_), Ty::Infer(_)) => App { + (Self::Tuple(_, tuple_span), Ty::Infer(_)) => App { holes: Vec::new(), constraints: vec![Constraint::Eq { expected: param.clone(), actual: self.to_ty(), - span, + span: *tuple_span, }], errors: Vec::new(), }, - (Self::Tuple(_), _) => App { + (Self::Tuple(_, tuple_span), _) => App { holes: Vec::new(), constraints: Vec::new(), errors: vec![Error(ErrorKind::TyMismatch( param.display(), self.to_ty().display(), - span, + *tuple_span, ))], }, } @@ -410,8 +408,8 @@ impl ArgTy { pub(super) fn to_ty(&self) -> Ty { match self { - ArgTy::Hole(ty) | ArgTy::Given(ty) => ty.clone(), - ArgTy::Tuple(items) => Ty::Tuple(items.iter().map(Self::to_ty).collect()), + ArgTy::Hole(ty, _) | ArgTy::Given(ty, _) => ty.clone(), + ArgTy::Tuple(items, _) => Ty::Tuple(items.iter().map(Self::to_ty).collect()), } } } @@ -1039,7 +1037,7 @@ fn check_call(callee: Ty, input: &ArgTy, output: Ty, span: Span) -> (Vec 1 { Ty::Arrow(Rc::new(Arrow { kind: arrow.kind, diff --git a/source/compiler/qsc_frontend/src/typeck/rules.rs b/source/compiler/qsc_frontend/src/typeck/rules.rs index 677d0cf0f2..f2a062e782 100644 --- a/source/compiler/qsc_frontend/src/typeck/rules.rs +++ b/source/compiler/qsc_frontend/src/typeck/rules.rs @@ -264,25 +264,51 @@ impl<'a> Context<'a> { } ExprKind::BinOp(op, lhs, rhs) => self.infer_binop(expr.span, *op, lhs, rhs), ExprKind::Block(block) => self.infer_block(block), - ExprKind::Call(callee, input) => { - let callee = self.infer_expr(callee); - let input = if has_holes(input) { - self.infer_hole_tuple_arg(input) + ExprKind::Call(callee_expr, input_expr) => { + let callee = self.infer_expr(callee_expr); + let input_expr = &**input_expr; + let input = if has_holes(input_expr) { + self.infer_hole_tuple_arg(input_expr) } else { - let ty = self.infer_expr(input); + let ty = self.infer_expr(input_expr); // If the outermost element is a tuple, we must wrap it in an `ArgTy::Tuple`. - match ty { + if let Partial { + ty: Ty::Tuple(tys), + diverges, + } = ty + { + let spans: Vec<_> = if let ExprKind::Tuple(items) = input_expr.kind.as_ref() + { + items.iter().map(|item| item.span).collect() + } else if let ExprKind::Paren(inner) = input_expr.kind.as_ref() { + if let ExprKind::Tuple(items) = inner.kind.as_ref() { + items.iter().map(|item| item.span).collect() + } else { + panic!("unexpected syntax kind: {:?}", inner.kind) + } + } else { + panic!("unexpected syntax kind: {:?}", input_expr.kind) + }; Partial { - ty: Ty::Tuple(tys), + ty: ArgTy::Tuple( + tys.into_iter() + .zip(spans) + .map(|(ty, span)| ArgTy::Given(ty, span)) + .collect(), + input_expr.span, + ), diverges, - } => Partial { - ty: ArgTy::Tuple(tys.into_iter().map(ArgTy::Given).collect()), - diverges, - }, - _ => Partial { - ty: ArgTy::Given(ty.ty), + } + } else { + let arg_span = if let ExprKind::Paren(inner) = input_expr.kind.as_ref() { + inner.span + } else { + input_expr.span + }; + Partial { + ty: ArgTy::Given(ty.ty, arg_span), diverges: false, - }, + } } }; let output_ty = if callee.ty == Ty::Err { @@ -723,7 +749,7 @@ impl<'a> Context<'a> { ExprKind::Hole => { let ty = self.inferrer.fresh_ty(TySource::not_divergent(expr.span)); self.record(expr.id, ty.clone()); - converge(ArgTy::Hole(ty)) + converge(ArgTy::Hole(ty, expr.span)) } ExprKind::Paren(inner) => { let inner = self.infer_hole_tuple_arg(inner); @@ -739,9 +765,19 @@ impl<'a> Context<'a> { tys.push(item.ty); } self.record(expr.id, Ty::Tuple(tys.iter().map(ArgTy::to_ty).collect())); - self.diverge_if_map(ArgTy::Given, diverges, converge(ArgTy::Tuple(tys))) + let span = expr.span; + self.diverge_if_map( + // This seems like it could be the span of the (first?) divergent + // tuple item, but the value doesn't seem to justify the complexity + |ty| ArgTy::Given(ty, span), + diverges, + converge(ArgTy::Tuple(tys, span)), + ) + } + _ => { + let span = expr.span; + self.infer_expr(expr).map(|ty| ArgTy::Given(ty, span)) } - _ => self.infer_expr(expr).map(ArgTy::Given), } } diff --git a/source/compiler/qsc_frontend/src/typeck/tests.rs b/source/compiler/qsc_frontend/src/typeck/tests.rs index 88832b7997..169315b13e 100644 --- a/source/compiler/qsc_frontend/src/typeck/tests.rs +++ b/source/compiler/qsc_frontend/src/typeck/tests.rs @@ -476,15 +476,115 @@ fn int_as_double_error() { } "}, "Microsoft.Quantum.Convert.IntAsDouble(false)", - &expect![[r#" + &expect![[r##" #8 62-71 "(a : Int)" : ? #9 63-70 "a : Int" : ? #18 103-147 "Microsoft.Quantum.Convert.IntAsDouble(false)" : Double #19 103-140 "Microsoft.Quantum.Convert.IntAsDouble" : (Int -> Double) #25 140-147 "(false)" : Bool #26 141-146 "false" : Bool - Error(Type(Error(TyMismatch("Int", "Bool", Span { lo: 103, hi: 147 })))) - "#]], + Error(Type(Error(TyMismatch("Int", "Bool", Span { lo: 141, hi: 146 })))) + "##]], + ); +} + +#[test] +fn ty_mismatch_span_tuple1_to_given() { + check( + indoc! {" + namespace Namespace { + function F(a : Int) : Double { 1.0 } + } + "}, + "Namespace.F((1,))", + &expect![[r##" + #6 36-45 "(a : Int)" : Int + #7 37-44 "a : Int" : Int + #15 55-62 "{ 1.0 }" : Double + #17 57-60 "1.0" : Double + #18 65-82 "Namespace.F((1,))" : Double + #19 65-76 "Namespace.F" : (Int -> Double) + #23 76-82 "((1,))" : (Int,) + #24 77-81 "(1,)" : (Int,) + #25 78-79 "1" : Int + Error(Type(Error(TyMismatch("Int", "(Int,)", Span { lo: 76, hi: 82 })))) + "##]], // 77-81 would be better, but the parens are fine + ); +} + +#[test] +fn ty_mismatch_span_given_to_tuple1() { + check( + indoc! {" + namespace Namespace { + function F((a : Int,)) : Double { 1.0 } + } + "}, + "Namespace.F(1)", + &expect![[r##" + #6 36-48 "((a : Int,))" : (Int,) + #7 37-47 "(a : Int,)" : (Int,) + #8 38-45 "a : Int" : Int + #16 58-65 "{ 1.0 }" : Double + #18 60-63 "1.0" : Double + #19 68-82 "Namespace.F(1)" : Double + #20 68-79 "Namespace.F" : ((Int,) -> Double) + #24 79-82 "(1)" : Int + #25 80-81 "1" : Int + Error(Type(Error(TyMismatch("(Int,)", "Int", Span { lo: 80, hi: 81 })))) + "##]], + ); +} + +#[test] +fn ty_mismatch_span_tuple1_to_tuple1() { + check( + indoc! {" + namespace Namespace { + function F((a : Int,)) : Double { 1.0 } + } + "}, + "Namespace.F((1.,))", + &expect![[r##" + #6 36-48 "((a : Int,))" : (Int,) + #7 37-47 "(a : Int,)" : (Int,) + #8 38-45 "a : Int" : Int + #16 58-65 "{ 1.0 }" : Double + #18 60-63 "1.0" : Double + #19 68-86 "Namespace.F((1.,))" : Double + #20 68-79 "Namespace.F" : ((Int,) -> Double) + #24 79-86 "((1.,))" : (Double,) + #25 80-85 "(1.,)" : (Double,) + #26 81-83 "1." : Double + Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 81, hi: 83 })))) + "##]], + ); +} + +#[test] +fn ty_mismatch_span_tuple2_to_tuple2() { + check( + indoc! {" + namespace Namespace { + function F((a : Int, b: Int)) : Double { 1.0 } + } + "}, + "Namespace.F((1.,2))", + &expect![[r##" + #6 36-55 "((a : Int, b: Int))" : (Int, Int) + #7 37-54 "(a : Int, b: Int)" : (Int, Int) + #8 38-45 "a : Int" : Int + #13 47-53 "b: Int" : Int + #21 65-72 "{ 1.0 }" : Double + #23 67-70 "1.0" : Double + #24 75-94 "Namespace.F((1.,2))" : Double + #25 75-86 "Namespace.F" : ((Int, Int) -> Double) + #29 86-94 "((1.,2))" : (Double, Int) + #30 87-93 "(1.,2)" : (Double, Int) + #31 88-90 "1." : Double + #32 91-92 "2" : Int + Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 88, hi: 90 })))) + "##]], ); } @@ -507,9 +607,9 @@ fn length_type_error() { #24 92-93 "1" : Int #25 95-96 "2" : Int #26 98-99 "3" : Int - Error(Type(Error(TyMismatch("?[]", "(Int, Int, Int)", Span { lo: 84, hi: 101 })))) + Error(Type(Error(TyMismatch("?[]", "(Int, Int, Int)", Span { lo: 90, hi: 101 })))) Error(Type(Error(AmbiguousTy(Span { lo: 84, hi: 90 })))) - "##]], + "##]], // 91-100 would be better, but the parens are fine ); } @@ -538,7 +638,7 @@ fn single_arg_for_tuple() { #31 124-126 "Ry" : ((Double, Qubit) => Unit is Adj + Ctl) #34 126-129 "(q)" : Qubit #35 127-128 "q" : Qubit - Error(Type(Error(TyMismatch("(Double, Qubit)", "Qubit", Span { lo: 124, hi: 129 })))) + Error(Type(Error(TyMismatch("(Double, Qubit)", "Qubit", Span { lo: 127, hi: 128 })))) "##]], ); } @@ -1732,7 +1832,7 @@ fn call_controlled_error() { Controlled A.Foo([1], q); } "}, - &expect![[r#" + &expect![[r##" #6 31-42 "(q : Qubit)" : Qubit #7 32-41 "q : Qubit" : Qubit #17 72-75 "..." : Qubit @@ -1752,8 +1852,8 @@ fn call_controlled_error() { #39 163-166 "[1]" : Int[] #40 164-165 "1" : Int #41 168-169 "q" : Qubit - Error(Type(Error(TyMismatch("Qubit", "Int", Span { lo: 146, hi: 170 })))) - "#]], + Error(Type(Error(TyMismatch("Qubit", "Int", Span { lo: 163, hi: 166 })))) + "##]], ); } @@ -1949,7 +2049,7 @@ fn fail_in_call_args_checks_arity() { #33 64-65 "1" : Int #34 67-78 "fail \"true\"" : Int #35 72-78 "\"true\"" : String - Error(Type(Error(TyMismatch("(Int, Int, Int)", "(Int, ?)", Span { lo: 60, hi: 79 })))) + Error(Type(Error(TyMismatch("(Int, Int, Int)", "(Int, ?)", Span { lo: 63, hi: 79 })))) "##]], ); } @@ -1979,7 +2079,7 @@ fn fail_in_call_args_checks_non_divergent_types() { #34 67-78 "fail \"true\"" : Int #35 72-78 "\"true\"" : String #36 80-83 "3.0" : Double - Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 60, hi: 84 })))) + Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 80, hi: 83 })))) "##]], ); } @@ -2145,7 +2245,7 @@ fn return_in_call_args_checks_arity() { #33 64-65 "1" : Int #34 67-80 "return \"true\"" : Int #35 74-80 "\"true\"" : String - Error(Type(Error(TyMismatch("(Int, Int, Int)", "(Int, ?)", Span { lo: 60, hi: 81 })))) + Error(Type(Error(TyMismatch("(Int, Int, Int)", "(Int, ?)", Span { lo: 63, hi: 81 })))) "##]], ); } @@ -2175,7 +2275,7 @@ fn return_in_call_args_checks_non_divergent_types() { #34 67-80 "return \"true\"" : Int #35 74-80 "\"true\"" : String #36 82-85 "3.0" : Double - Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 60, hi: 86 })))) + Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 82, hi: 85 })))) "##]], ); } @@ -2767,7 +2867,7 @@ fn newtype_cons_wrong_input() { #19 70-76 "NewInt" : (Int -> UDT<"NewInt": Item 1 (Package 2)>) #22 76-81 "(5.0)" : Double #23 77-80 "5.0" : Double - Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 70, hi: 81 })))) + Error(Type(Error(TyMismatch("Int", "Double", Span { lo: 77, hi: 80 })))) "##]], ); } @@ -4021,7 +4121,7 @@ fn partial_app_too_many_args() { function Foo(x : Int) : Int { x } let f = Foo(1, _, _); }"}, - &expect![[r#" + &expect![[r##" #1 0-67 "{\n function Foo(x : Int) : Int { x }\n let f = Foo(1, _, _);\n}" : Unit #2 0-67 "{\n function Foo(x : Int) : Int { x }\n let f = Foo(1, _, _);\n}" : Unit #7 18-27 "(x : Int)" : Int @@ -4035,10 +4135,10 @@ fn partial_app_too_many_args() { #29 56-57 "1" : Int #30 59-60 "_" : ?1 #31 62-63 "_" : ?2 - Error(Type(Error(TyMismatch("Int", "(Int, ?, ?)", Span { lo: 52, hi: 64 })))) + Error(Type(Error(TyMismatch("Int", "(Int, ?, ?)", Span { lo: 55, hi: 64 })))) Error(Type(Error(AmbiguousTy(Span { lo: 59, hi: 60 })))) Error(Type(Error(AmbiguousTy(Span { lo: 62, hi: 63 })))) - "#]], + "##]], ); } @@ -4134,7 +4234,7 @@ fn functors_in_arg_subset_of_ctl_adj() { operation Bar(q : Qubit) : () is Adj {} Foo(Bar); }", - &expect![[r#" + &expect![[r##" #1 0-150 "{\n operation Foo(op : Qubit => () is Adj + Ctl) : () {}\n operation Bar(q : Qubit) : () is Adj {}\n Foo(Bar);\n }" : Unit #2 0-150 "{\n operation Foo(op : Qubit => () is Adj + Ctl) : () {}\n operation Bar(q : Qubit) : () is Adj {}\n Foo(Bar);\n }" : Unit #7 27-58 "(op : Qubit => () is Adj + Ctl)" : (Qubit => Unit is Adj + Ctl) @@ -4147,8 +4247,8 @@ fn functors_in_arg_subset_of_ctl_adj() { #35 131-134 "Foo" : ((Qubit => Unit is Adj) => Unit) #38 134-139 "(Bar)" : (Qubit => Unit is Adj) #39 135-138 "Bar" : (Qubit => Unit is Adj) - Error(Type(Error(MissingFunctor(Value(CtlAdj), Value(Adj), Span { lo: 131, hi: 139 })))) - "#]], + Error(Type(Error(MissingFunctor(Value(CtlAdj), Value(Adj), Span { lo: 135, hi: 138 })))) + "##]], ); } @@ -4187,7 +4287,7 @@ fn functors_in_arg_nested_arrow_superset_of_adj() { operation Bar(op : Qubit => () is Adj + Ctl) : () {} Foo(Bar); }", - &expect![[r#" + &expect![[r##" #1 0-165 "{\n operation Foo(op : (Qubit => () is Adj) => ()) : () {}\n operation Bar(op : Qubit => () is Adj + Ctl) : () {}\n Foo(Bar);\n }" : Unit #2 0-165 "{\n operation Foo(op : (Qubit => () is Adj) => ()) : () {}\n operation Bar(op : Qubit => () is Adj + Ctl) : () {}\n Foo(Bar);\n }" : Unit #7 27-60 "(op : (Qubit => () is Adj) => ())" : ((Qubit => Unit is Adj) => Unit) @@ -4200,8 +4300,8 @@ fn functors_in_arg_nested_arrow_superset_of_adj() { #40 146-149 "Foo" : (((Qubit => Unit is Adj) => Unit) => Unit) #43 149-154 "(Bar)" : ((Qubit => Unit is Adj) => Unit) #44 150-153 "Bar" : ((Qubit => Unit is Adj) => Unit) - Error(Type(Error(MissingFunctor(Value(CtlAdj), Value(Adj), Span { lo: 146, hi: 154 })))) - "#]], + Error(Type(Error(MissingFunctor(Value(CtlAdj), Value(Adj), Span { lo: 150, hi: 153 })))) + "##]], ); } @@ -4293,7 +4393,7 @@ fn functors_in_arg_array_subset_of_adj() { operation Bar(q : Qubit) : () {} Foo([Bar]); }", - &expect![[r#" + &expect![[r##" #1 0-144 "{\n operation Foo(ops : (Qubit => () is Adj)[]) : () {}\n operation Bar(q : Qubit) : () {}\n Foo([Bar]);\n }" : Unit #2 0-144 "{\n operation Foo(ops : (Qubit => () is Adj)[]) : () {}\n operation Bar(q : Qubit) : () {}\n Foo([Bar]);\n }" : Unit #7 27-57 "(ops : (Qubit => () is Adj)[])" : (Qubit => Unit is Adj)[] @@ -4307,8 +4407,8 @@ fn functors_in_arg_array_subset_of_adj() { #37 126-133 "([Bar])" : (Qubit => Unit)[] #38 127-132 "[Bar]" : (Qubit => Unit)[] #39 128-131 "Bar" : (Qubit => Unit) - Error(Type(Error(MissingFunctor(Value(Adj), Value(Empty), Span { lo: 123, hi: 133 })))) - "#]], + Error(Type(Error(MissingFunctor(Value(Adj), Value(Empty), Span { lo: 127, hi: 132 })))) + "##]], ); } diff --git a/source/compiler/qsc_frontend/src/typeck/tests/bounded_polymorphism.rs b/source/compiler/qsc_frontend/src/typeck/tests/bounded_polymorphism.rs index 8c93c537dd..a10c6de5cc 100644 --- a/source/compiler/qsc_frontend/src/typeck/tests/bounded_polymorphism.rs +++ b/source/compiler/qsc_frontend/src/typeck/tests/bounded_polymorphism.rs @@ -380,8 +380,8 @@ fn transitive_class_check_fail() { #80 516-519 "Foo" : (BigInt -> BigInt) #83 519-524 "(10L)" : BigInt #84 520-523 "10L" : BigInt - Error(Type(Error(MissingClassInteger("'F", Span { lo: 259, hi: 265 })))) - Error(Type(Error(MissingClassInteger("Double", Span { lo: 474, hi: 482 })))) + Error(Type(Error(MissingClassInteger("'F", Span { lo: 263, hi: 264 })))) + Error(Type(Error(MissingClassInteger("Double", Span { lo: 478, hi: 481 })))) "##]], ); } @@ -606,8 +606,8 @@ fn integral_fail() { #45 210-213 "Foo" : (Bool -> Bool) #48 213-219 "(true)" : Bool #49 214-218 "true" : Bool - Error(Type(Error(MissingClassInteger("Double", Span { lo: 176, hi: 184 })))) - Error(Type(Error(MissingClassInteger("Bool", Span { lo: 210, hi: 219 })))) + Error(Type(Error(MissingClassInteger("Double", Span { lo: 180, hi: 183 })))) + Error(Type(Error(MissingClassInteger("Bool", Span { lo: 214, hi: 218 })))) "##]], ); } @@ -736,8 +736,8 @@ fn show_and_eq_should_fail() { #69 344-352 "(1, \"2\")" : (Int, String) #70 345-346 "1" : Int #71 348-351 "\"2\"" : String - Error(Type(Error(TyMismatch("Int", "Bool", Span { lo: 303, hi: 315 })))) - Error(Type(Error(TyMismatch("Int", "String", Span { lo: 341, hi: 352 })))) + Error(Type(Error(TyMismatch("Int", "Bool", Span { lo: 310, hi: 314 })))) + Error(Type(Error(TyMismatch("Int", "String", Span { lo: 348, hi: 351 })))) "##]], ); } diff --git a/source/wasm/src/tests.rs b/source/wasm/src/tests.rs index 08c3e144e2..4098352310 100644 --- a/source/wasm/src/tests.rs +++ b/source/wasm/src/tests.rs @@ -105,7 +105,7 @@ fn fail_ry() { let _result = run_internal( SourceMap::new([("test.qs".into(), code.into())], Some(expr.into())), |msg| { - expect![[r#"{"result":{"code":"Qsc.TypeCk.TyMismatch","errors":[{"diagnostic":{"code":"Qsc.TypeCk.TyMismatch","message":"type error: expected (Double, Qubit), found Qubit","range":{"end":{"character":18,"line":3},"start":{"character":12,"line":3}},"severity":"error"},"document":"test.qs","stack":null}],"message":"type error: expected (Double, Qubit), found Qubit","range":{"end":{"character":18,"line":3},"start":{"character":12,"line":3}},"severity":"error"},"success":false,"type":"Result"}"#]].assert_eq(msg); + expect![[r#"{"result":{"code":"Qsc.TypeCk.TyMismatch","errors":[{"diagnostic":{"code":"Qsc.TypeCk.TyMismatch","message":"type error: expected (Double, Qubit), found Qubit","range":{"end":{"character":17,"line":3},"start":{"character":15,"line":3}},"severity":"error"},"document":"test.qs","stack":null}],"message":"type error: expected (Double, Qubit), found Qubit","range":{"end":{"character":17,"line":3},"start":{"character":15,"line":3}},"severity":"error"},"success":false,"type":"Result"}"#]].assert_eq(msg); count.set(count.get() + 1); }, 1,