From 8729391e5363af33111fb646cb3d87b7e1d1650b Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 26 Jun 2021 10:46:23 -0700 Subject: [PATCH] [glsl-in] Fix function lookup First look for exact matches before trying the implicit lookup. Otherwise, finding two wrong matches first will result in an ambiguous function error. This logic could use with a bit of a cleanup, keeping track of a closer score and doing more exact matching on types, but this might be good enough for now. --- src/front/glsl/functions.rs | 14 ++++++++++---- src/front/glsl/parser_tests.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index bd9b443fad..36cf739854 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -507,6 +507,7 @@ impl Program<'_> { })?; let mut maybe_decl = None; + let mut ambiguous = false; 'outer: for decl in declarations { if args.len() != decl.parameters.len() { @@ -538,17 +539,22 @@ impl Program<'_> { if exact { maybe_decl = Some(decl); + ambiguous = false; break; } else if maybe_decl.is_some() { - return Err(ErrorKind::SemanticError( - meta, - format!("Ambiguous best function for '{}'", name).into(), - )); + ambiguous = true; } else { maybe_decl = Some(decl) } } + if ambiguous { + return Err(ErrorKind::SemanticError( + meta, + format!("Ambiguous best function for '{}'", name).into(), + )); + } + let decl = maybe_decl.ok_or_else(|| { ErrorKind::SemanticError( meta, diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index 4b1b9ae32a..f555ec2dce 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -463,6 +463,32 @@ fn constants() { assert!(constants.next().is_none()); } +#[test] +fn function_overloading() { + let mut entry_points = crate::FastHashMap::default(); + entry_points.insert("".to_string(), ShaderStage::Vertex); + + parse_program( + r#" + # version 450 + + float saturate(float v) { return clamp(v, 0.0, 1.0); } + vec2 saturate(vec2 v) { return clamp(v, vec2(0.0), vec2(1.0)); } + vec3 saturate(vec3 v) { return clamp(v, vec3(0.0), vec3(1.0)); } + vec4 saturate(vec4 v) { return clamp(v, vec4(0.0), vec4(1.0)); } + + void main() { + float v1 = saturate(1.5); + vec2 v2 = saturate(vec2(0.5, 1.5)); + vec3 v3 = saturate(vec3(0.5, 1.5, 2.5)); + vec3 v4 = saturate(vec4(0.5, 1.5, 2.5, 3.5)); + } + "#, + &entry_points, + ) + .unwrap(); +} + #[test] fn implicit_conversions() { let mut entry_points = crate::FastHashMap::default();